<!DOCTYPE html>
<html lang="en-US" dir="ltr">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <title>vue3.0 | 前端码农</title>
    <meta name="description" content="前端码农手记">
    <link rel="preload stylesheet" href="/fe-handbook/document/assets/style.c131dda6.css" as="style">
    <script type="module" src="/fe-handbook/document/assets/app.fb33e324.js"></script>
    <link rel="preload" href="/fe-handbook/document/assets/inter-roman-latin.2ed14f66.woff2" as="font" type="font/woff2" crossorigin="">
  <link rel="modulepreload" href="/fe-handbook/document/assets/chunks/framework.e1becf5d.js">
  <link rel="modulepreload" href="/fe-handbook/document/assets/chunks/theme.ebfdf2c7.js">
  <link rel="modulepreload" href="/fe-handbook/document/assets/pages_vue_vue3.0.md.21ba1254.lean.js">
  <link rel="icon" type="image/svg+xml" href="images/logo.svg">
  <script id="check-dark-light">(()=>{const e=localStorage.getItem("vitepress-theme-appearance")||"",a=window.matchMedia("(prefers-color-scheme: dark)").matches;(!e||e==="auto"?a:e==="dark")&&document.documentElement.classList.add("dark")})();</script>
  </head>
  <body>
    <div id="app"><div class="Layout" data-v-bffce215><!--[--><!--]--><!--[--><span tabindex="-1" data-v-73e3a132></span><a href="#VPContent" class="VPSkipLink visually-hidden" data-v-73e3a132> Skip to content </a><!--]--><!----><header class="VPNav" data-v-bffce215 data-v-5bdc5df3><div class="VPNavBar has-sidebar" data-v-5bdc5df3 data-v-c388e33c><div class="container" data-v-c388e33c><div class="title" data-v-c388e33c><div class="VPNavBarTitle has-sidebar" data-v-c388e33c data-v-1ab7b21f><a class="title" href="/fe-handbook/document/" data-v-1ab7b21f><!--[--><!--]--><!--[--><img class="VPImage logo" src="/fe-handbook/document/images/logo.svg" alt data-v-dc109a54><!--]--><!--[-->前端码农<!--]--><!--[--><!--]--></a></div></div><div class="content" data-v-c388e33c><div class="curtain" data-v-c388e33c></div><div class="content-body" data-v-c388e33c><!--[--><!--]--><div class="VPNavBarSearch search" style="--vp-meta-key:&#39;Meta&#39;;" data-v-c388e33c><!----></div><nav aria-labelledby="main-nav-aria-label" class="VPNavBarMenu menu" data-v-c388e33c data-v-f732b5d0><span id="main-nav-aria-label" class="visually-hidden" data-v-f732b5d0>Main Navigation</span><!--[--><!--[--><a class="VPLink link VPNavBarMenuLink" href="/fe-handbook/document/" tabindex="0" data-v-f732b5d0 data-v-b7aed9c7 data-v-f3ed0000><!--[-->主页<!--]--><!----></a><!--]--><!--[--><a class="VPLink link VPNavBarMenuLink" href="/fe-handbook/document/pages/guide.html" tabindex="0" data-v-f732b5d0 data-v-b7aed9c7 data-v-f3ed0000><!--[-->指南<!--]--><!----></a><!--]--><!--[--><a class="VPLink link VPNavBarMenuLink" href="/fe-handbook/document/pages/updateLog.html" tabindex="0" data-v-f732b5d0 data-v-b7aed9c7 data-v-f3ed0000><!--[-->更新日志<!--]--><!----></a><!--]--><!--]--></nav><!----><div class="VPNavBarAppearance appearance" data-v-c388e33c data-v-5e9f0637><label title="toggle dark mode" data-v-5e9f0637 data-v-67878c63><button class="VPSwitch VPSwitchAppearance" type="button" role="switch" aria-checked="false" data-v-67878c63 data-v-92d8f6fb><span class="check" data-v-92d8f6fb><span class="icon" data-v-92d8f6fb><!--[--><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="sun" data-v-67878c63><path d="M12,18c-3.3,0-6-2.7-6-6s2.7-6,6-6s6,2.7,6,6S15.3,18,12,18zM12,8c-2.2,0-4,1.8-4,4c0,2.2,1.8,4,4,4c2.2,0,4-1.8,4-4C16,9.8,14.2,8,12,8z"></path><path d="M12,4c-0.6,0-1-0.4-1-1V1c0-0.6,0.4-1,1-1s1,0.4,1,1v2C13,3.6,12.6,4,12,4z"></path><path d="M12,24c-0.6,0-1-0.4-1-1v-2c0-0.6,0.4-1,1-1s1,0.4,1,1v2C13,23.6,12.6,24,12,24z"></path><path d="M5.6,6.6c-0.3,0-0.5-0.1-0.7-0.3L3.5,4.9c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l1.4,1.4c0.4,0.4,0.4,1,0,1.4C6.2,6.5,5.9,6.6,5.6,6.6z"></path><path d="M19.8,20.8c-0.3,0-0.5-0.1-0.7-0.3l-1.4-1.4c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l1.4,1.4c0.4,0.4,0.4,1,0,1.4C20.3,20.7,20,20.8,19.8,20.8z"></path><path d="M3,13H1c-0.6,0-1-0.4-1-1s0.4-1,1-1h2c0.6,0,1,0.4,1,1S3.6,13,3,13z"></path><path d="M23,13h-2c-0.6,0-1-0.4-1-1s0.4-1,1-1h2c0.6,0,1,0.4,1,1S23.6,13,23,13z"></path><path d="M4.2,20.8c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l1.4-1.4c0.4-0.4,1-0.4,1.4,0s0.4,1,0,1.4l-1.4,1.4C4.7,20.7,4.5,20.8,4.2,20.8z"></path><path d="M18.4,6.6c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l1.4-1.4c0.4-0.4,1-0.4,1.4,0s0.4,1,0,1.4l-1.4,1.4C18.9,6.5,18.6,6.6,18.4,6.6z"></path></svg><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="moon" data-v-67878c63><path d="M12.1,22c-0.3,0-0.6,0-0.9,0c-5.5-0.5-9.5-5.4-9-10.9c0.4-4.8,4.2-8.6,9-9c0.4,0,0.8,0.2,1,0.5c0.2,0.3,0.2,0.8-0.1,1.1c-2,2.7-1.4,6.4,1.3,8.4c2.1,1.6,5,1.6,7.1,0c0.3-0.2,0.7-0.3,1.1-0.1c0.3,0.2,0.5,0.6,0.5,1c-0.2,2.7-1.5,5.1-3.6,6.8C16.6,21.2,14.4,22,12.1,22zM9.3,4.4c-2.9,1-5,3.6-5.2,6.8c-0.4,4.4,2.8,8.3,7.2,8.7c2.1,0.2,4.2-0.4,5.8-1.8c1.1-0.9,1.9-2.1,2.4-3.4c-2.5,0.9-5.3,0.5-7.5-1.1C9.2,11.4,8.1,7.7,9.3,4.4z"></path></svg><!--]--></span></span></button></label></div><div class="VPSocialLinks VPNavBarSocialLinks social-links" data-v-c388e33c data-v-ef6192dc data-v-b8f6762d><!--[--><!--]--></div><div class="VPFlyout VPNavBarExtra extra" data-v-c388e33c data-v-c8c2ae4b data-v-6afe904b><button type="button" class="button" aria-haspopup="true" aria-expanded="false" aria-label="extra navigation" data-v-6afe904b><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="icon" data-v-6afe904b><circle cx="12" cy="12" r="2"></circle><circle cx="19" cy="12" r="2"></circle><circle cx="5" cy="12" r="2"></circle></svg></button><div class="menu" data-v-6afe904b><div class="VPMenu" data-v-6afe904b data-v-e42ed9b3><!----><!--[--><!--[--><!----><div class="group" data-v-c8c2ae4b><div class="item appearance" data-v-c8c2ae4b><p class="label" data-v-c8c2ae4b>Appearance</p><div class="appearance-action" data-v-c8c2ae4b><label title="toggle dark mode" data-v-c8c2ae4b data-v-67878c63><button class="VPSwitch VPSwitchAppearance" type="button" role="switch" aria-checked="false" data-v-67878c63 data-v-92d8f6fb><span class="check" data-v-92d8f6fb><span class="icon" data-v-92d8f6fb><!--[--><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="sun" data-v-67878c63><path d="M12,18c-3.3,0-6-2.7-6-6s2.7-6,6-6s6,2.7,6,6S15.3,18,12,18zM12,8c-2.2,0-4,1.8-4,4c0,2.2,1.8,4,4,4c2.2,0,4-1.8,4-4C16,9.8,14.2,8,12,8z"></path><path d="M12,4c-0.6,0-1-0.4-1-1V1c0-0.6,0.4-1,1-1s1,0.4,1,1v2C13,3.6,12.6,4,12,4z"></path><path d="M12,24c-0.6,0-1-0.4-1-1v-2c0-0.6,0.4-1,1-1s1,0.4,1,1v2C13,23.6,12.6,24,12,24z"></path><path d="M5.6,6.6c-0.3,0-0.5-0.1-0.7-0.3L3.5,4.9c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l1.4,1.4c0.4,0.4,0.4,1,0,1.4C6.2,6.5,5.9,6.6,5.6,6.6z"></path><path d="M19.8,20.8c-0.3,0-0.5-0.1-0.7-0.3l-1.4-1.4c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l1.4,1.4c0.4,0.4,0.4,1,0,1.4C20.3,20.7,20,20.8,19.8,20.8z"></path><path d="M3,13H1c-0.6,0-1-0.4-1-1s0.4-1,1-1h2c0.6,0,1,0.4,1,1S3.6,13,3,13z"></path><path d="M23,13h-2c-0.6,0-1-0.4-1-1s0.4-1,1-1h2c0.6,0,1,0.4,1,1S23.6,13,23,13z"></path><path d="M4.2,20.8c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l1.4-1.4c0.4-0.4,1-0.4,1.4,0s0.4,1,0,1.4l-1.4,1.4C4.7,20.7,4.5,20.8,4.2,20.8z"></path><path d="M18.4,6.6c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l1.4-1.4c0.4-0.4,1-0.4,1.4,0s0.4,1,0,1.4l-1.4,1.4C18.9,6.5,18.6,6.6,18.4,6.6z"></path></svg><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="moon" data-v-67878c63><path d="M12.1,22c-0.3,0-0.6,0-0.9,0c-5.5-0.5-9.5-5.4-9-10.9c0.4-4.8,4.2-8.6,9-9c0.4,0,0.8,0.2,1,0.5c0.2,0.3,0.2,0.8-0.1,1.1c-2,2.7-1.4,6.4,1.3,8.4c2.1,1.6,5,1.6,7.1,0c0.3-0.2,0.7-0.3,1.1-0.1c0.3,0.2,0.5,0.6,0.5,1c-0.2,2.7-1.5,5.1-3.6,6.8C16.6,21.2,14.4,22,12.1,22zM9.3,4.4c-2.9,1-5,3.6-5.2,6.8c-0.4,4.4,2.8,8.3,7.2,8.7c2.1,0.2,4.2-0.4,5.8-1.8c1.1-0.9,1.9-2.1,2.4-3.4c-2.5,0.9-5.3,0.5-7.5-1.1C9.2,11.4,8.1,7.7,9.3,4.4z"></path></svg><!--]--></span></span></button></label></div></div></div><div class="group" data-v-c8c2ae4b><div class="item social-links" data-v-c8c2ae4b><div class="VPSocialLinks social-links-list" data-v-c8c2ae4b data-v-b8f6762d><!--[--><!--]--></div></div></div><!--]--><!--]--></div></div></div><!--[--><!--]--><button type="button" class="VPNavBarHamburger hamburger" aria-label="mobile navigation" aria-expanded="false" aria-controls="VPNavScreen" data-v-c388e33c data-v-6bee1efd><span class="container" data-v-6bee1efd><span class="top" data-v-6bee1efd></span><span class="middle" data-v-6bee1efd></span><span class="bottom" data-v-6bee1efd></span></span></button></div></div></div></div><!----></header><div class="VPLocalNav" data-v-bffce215 data-v-ba1b30d0><button class="menu" aria-expanded="false" aria-controls="VPSidebarNav" data-v-ba1b30d0><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="menu-icon" data-v-ba1b30d0><path d="M17,11H3c-0.6,0-1-0.4-1-1s0.4-1,1-1h14c0.6,0,1,0.4,1,1S17.6,11,17,11z"></path><path d="M21,7H3C2.4,7,2,6.6,2,6s0.4-1,1-1h18c0.6,0,1,0.4,1,1S21.6,7,21,7z"></path><path d="M21,15H3c-0.6,0-1-0.4-1-1s0.4-1,1-1h18c0.6,0,1,0.4,1,1S21.6,15,21,15z"></path><path d="M17,19H3c-0.6,0-1-0.4-1-1s0.4-1,1-1h14c0.6,0,1,0.4,1,1S17.6,19,17,19z"></path></svg><span class="menu-text" data-v-ba1b30d0>Menu</span></button><div class="VPLocalNavOutlineDropdown" style="--vp-vh:0px;" data-v-ba1b30d0 data-v-fb63c957><button data-v-fb63c957>Return to top</button><!----></div></div><aside class="VPSidebar" data-v-bffce215 data-v-fe05da0a><div class="curtain" data-v-fe05da0a></div><nav class="nav" id="VPSidebarNav" aria-labelledby="sidebar-aria-label" tabindex="-1" data-v-fe05da0a><span class="visually-hidden" id="sidebar-aria-label" data-v-fe05da0a> Sidebar Navigation </span><!--[--><!--]--><!--[--><div class="group" data-v-fe05da0a><section class="VPSidebarItem level-0 collapsible" data-v-fe05da0a data-v-0bb349fd><!----><div class="items" data-v-0bb349fd><!--[--><div class="VPSidebarItem level-1 is-link" data-v-0bb349fd data-v-0bb349fd><div class="item" data-v-0bb349fd><div class="indicator" data-v-0bb349fd></div><a class="VPLink link link" href="/fe-handbook/document/pages/guide.html" data-v-0bb349fd data-v-f3ed0000><!--[--><p class="text" data-v-0bb349fd>开发指南</p><!--]--><!----></a><!----></div><!----></div><!--]--></div></section></div><div class="group" data-v-fe05da0a><section class="VPSidebarItem level-0 collapsible" data-v-fe05da0a data-v-0bb349fd><div class="item" role="button" tabindex="0" data-v-0bb349fd><div class="indicator" data-v-0bb349fd></div><h2 class="text" data-v-0bb349fd>JavaScript高级程序设计</h2><div class="caret" role="button" aria-label="toggle section" tabindex="0" data-v-0bb349fd><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="caret-icon" data-v-0bb349fd><path d="M9,19c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l5.3-5.3L8.3,6.7c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l6,6c0.4,0.4,0.4,1,0,1.4l-6,6C9.5,18.9,9.3,19,9,19z"></path></svg></div></div><div class="items" data-v-0bb349fd><!--[--><div class="VPSidebarItem level-1 is-link" data-v-0bb349fd data-v-0bb349fd><div class="item" data-v-0bb349fd><div class="indicator" data-v-0bb349fd></div><a class="VPLink link link" href="/fe-handbook/document/pages/advancedProgramming/index.html" data-v-0bb349fd data-v-f3ed0000><!--[--><p class="text" data-v-0bb349fd>0.前言</p><!--]--><!----></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-0bb349fd data-v-0bb349fd><div class="item" data-v-0bb349fd><div class="indicator" data-v-0bb349fd></div><a class="VPLink link link" href="/fe-handbook/document/pages/advancedProgramming/chapterOne.html" data-v-0bb349fd data-v-f3ed0000><!--[--><p class="text" data-v-0bb349fd>1.什么是JavaScript</p><!--]--><!----></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-0bb349fd data-v-0bb349fd><div class="item" data-v-0bb349fd><div class="indicator" data-v-0bb349fd></div><a class="VPLink link link" href="/fe-handbook/document/pages/advancedProgramming/chapterTwo.html" data-v-0bb349fd data-v-f3ed0000><!--[--><p class="text" data-v-0bb349fd>2.HTML中的JavaScript</p><!--]--><!----></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-0bb349fd data-v-0bb349fd><div class="item" data-v-0bb349fd><div class="indicator" data-v-0bb349fd></div><a class="VPLink link link" href="/fe-handbook/document/pages/advancedProgramming/chapterThree.html" data-v-0bb349fd data-v-f3ed0000><!--[--><p class="text" data-v-0bb349fd>3.语言基础</p><!--]--><!----></a><!----></div><!----></div><!--]--></div></section></div><div class="group" data-v-fe05da0a><section class="VPSidebarItem level-0 collapsible has-active" data-v-fe05da0a data-v-0bb349fd><div class="item" role="button" tabindex="0" data-v-0bb349fd><div class="indicator" data-v-0bb349fd></div><h2 class="text" data-v-0bb349fd>vue技术栈</h2><div class="caret" role="button" aria-label="toggle section" tabindex="0" data-v-0bb349fd><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="caret-icon" data-v-0bb349fd><path d="M9,19c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l5.3-5.3L8.3,6.7c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l6,6c0.4,0.4,0.4,1,0,1.4l-6,6C9.5,18.9,9.3,19,9,19z"></path></svg></div></div><div class="items" data-v-0bb349fd><!--[--><div class="VPSidebarItem level-1 is-link" data-v-0bb349fd data-v-0bb349fd><div class="item" data-v-0bb349fd><div class="indicator" data-v-0bb349fd></div><a class="VPLink link link" href="/fe-handbook/document/pages/vue/vue2.0.html" data-v-0bb349fd data-v-f3ed0000><!--[--><p class="text" data-v-0bb349fd>vue2.0</p><!--]--><!----></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link is-active has-active" data-v-0bb349fd data-v-0bb349fd><div class="item" data-v-0bb349fd><div class="indicator" data-v-0bb349fd></div><a class="VPLink link link" href="/fe-handbook/document/pages/vue/vue3.0.html" data-v-0bb349fd data-v-f3ed0000><!--[--><p class="text" data-v-0bb349fd>vue3.0</p><!--]--><!----></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-0bb349fd data-v-0bb349fd><div class="item" data-v-0bb349fd><div class="indicator" data-v-0bb349fd></div><a class="VPLink link link" href="/fe-handbook/document/pages/vue/vuex4.0.html" data-v-0bb349fd data-v-f3ed0000><!--[--><p class="text" data-v-0bb349fd>vuex4.0</p><!--]--><!----></a><!----></div><!----></div><!--]--></div></section></div><div class="group" data-v-fe05da0a><section class="VPSidebarItem level-0 collapsible" data-v-fe05da0a data-v-0bb349fd><div class="item" role="button" tabindex="0" data-v-0bb349fd><div class="indicator" data-v-0bb349fd></div><h2 class="text" data-v-0bb349fd>react技术栈</h2><div class="caret" role="button" aria-label="toggle section" tabindex="0" data-v-0bb349fd><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="caret-icon" data-v-0bb349fd><path d="M9,19c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l5.3-5.3L8.3,6.7c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l6,6c0.4,0.4,0.4,1,0,1.4l-6,6C9.5,18.9,9.3,19,9,19z"></path></svg></div></div><div class="items" data-v-0bb349fd><!--[--><div class="VPSidebarItem level-1 is-link" data-v-0bb349fd data-v-0bb349fd><div class="item" data-v-0bb349fd><div class="indicator" data-v-0bb349fd></div><a class="VPLink link link" href="/fe-handbook/document/pages/react/react.html" data-v-0bb349fd data-v-f3ed0000><!--[--><p class="text" data-v-0bb349fd>react18</p><!--]--><!----></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-0bb349fd data-v-0bb349fd><div class="item" data-v-0bb349fd><div class="indicator" data-v-0bb349fd></div><a class="VPLink link link" href="/fe-handbook/document/pages/react/redux.html" data-v-0bb349fd data-v-f3ed0000><!--[--><p class="text" data-v-0bb349fd>redux</p><!--]--><!----></a><!----></div><!----></div><!--]--></div></section></div><div class="group" data-v-fe05da0a><section class="VPSidebarItem level-0 collapsible" data-v-fe05da0a data-v-0bb349fd><div class="item" role="button" tabindex="0" data-v-0bb349fd><div class="indicator" data-v-0bb349fd></div><h2 class="text" data-v-0bb349fd>nodejs技术栈</h2><div class="caret" role="button" aria-label="toggle section" tabindex="0" data-v-0bb349fd><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="caret-icon" data-v-0bb349fd><path d="M9,19c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l5.3-5.3L8.3,6.7c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l6,6c0.4,0.4,0.4,1,0,1.4l-6,6C9.5,18.9,9.3,19,9,19z"></path></svg></div></div><div class="items" data-v-0bb349fd><!--[--><div class="VPSidebarItem level-1 is-link" data-v-0bb349fd data-v-0bb349fd><div class="item" data-v-0bb349fd><div class="indicator" data-v-0bb349fd></div><a class="VPLink link link" href="/fe-handbook/document/pages/nodeJS/index.html" data-v-0bb349fd data-v-f3ed0000><!--[--><p class="text" data-v-0bb349fd>nodeJS</p><!--]--><!----></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-0bb349fd data-v-0bb349fd><div class="item" data-v-0bb349fd><div class="indicator" data-v-0bb349fd></div><a class="VPLink link link" href="/fe-handbook/document/pages/nodeJS/nest.html" data-v-0bb349fd data-v-f3ed0000><!--[--><p class="text" data-v-0bb349fd>nest</p><!--]--><!----></a><!----></div><!----></div><!--]--></div></section></div><div class="group" data-v-fe05da0a><section class="VPSidebarItem level-0 collapsible" data-v-fe05da0a data-v-0bb349fd><div class="item" role="button" tabindex="0" data-v-0bb349fd><div class="indicator" data-v-0bb349fd></div><h2 class="text" data-v-0bb349fd>flutter</h2><div class="caret" role="button" aria-label="toggle section" tabindex="0" data-v-0bb349fd><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="caret-icon" data-v-0bb349fd><path d="M9,19c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l5.3-5.3L8.3,6.7c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l6,6c0.4,0.4,0.4,1,0,1.4l-6,6C9.5,18.9,9.3,19,9,19z"></path></svg></div></div><div class="items" data-v-0bb349fd><!--[--><div class="VPSidebarItem level-1 is-link" data-v-0bb349fd data-v-0bb349fd><div class="item" data-v-0bb349fd><div class="indicator" data-v-0bb349fd></div><a class="VPLink link link" href="/fe-handbook/document/pages/flutter/index.html" data-v-0bb349fd data-v-f3ed0000><!--[--><p class="text" data-v-0bb349fd>flutter</p><!--]--><!----></a><!----></div><!----></div><!--]--></div></section></div><div class="group" data-v-fe05da0a><section class="VPSidebarItem level-0 collapsible" data-v-fe05da0a data-v-0bb349fd><div class="item" role="button" tabindex="0" data-v-0bb349fd><div class="indicator" data-v-0bb349fd></div><h2 class="text" data-v-0bb349fd>数据结构算法&设计模式</h2><div class="caret" role="button" aria-label="toggle section" tabindex="0" data-v-0bb349fd><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="caret-icon" data-v-0bb349fd><path d="M9,19c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l5.3-5.3L8.3,6.7c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l6,6c0.4,0.4,0.4,1,0,1.4l-6,6C9.5,18.9,9.3,19,9,19z"></path></svg></div></div><div class="items" data-v-0bb349fd><!--[--><div class="VPSidebarItem level-1 is-link" data-v-0bb349fd data-v-0bb349fd><div class="item" data-v-0bb349fd><div class="indicator" data-v-0bb349fd></div><a class="VPLink link link" href="/fe-handbook/document/pages/dataStructure.html" data-v-0bb349fd data-v-f3ed0000><!--[--><p class="text" data-v-0bb349fd>dataStructure</p><!--]--><!----></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-0bb349fd data-v-0bb349fd><div class="item" data-v-0bb349fd><div class="indicator" data-v-0bb349fd></div><a class="VPLink link link" href="/fe-handbook/document/pages/designPatterns.html" data-v-0bb349fd data-v-f3ed0000><!--[--><p class="text" data-v-0bb349fd>设计模式</p><!--]--><!----></a><!----></div><!----></div><!--]--></div></section></div><div class="group" data-v-fe05da0a><section class="VPSidebarItem level-0 collapsible" data-v-fe05da0a data-v-0bb349fd><div class="item" role="button" tabindex="0" data-v-0bb349fd><div class="indicator" data-v-0bb349fd></div><h2 class="text" data-v-0bb349fd>js基础进阶</h2><div class="caret" role="button" aria-label="toggle section" tabindex="0" data-v-0bb349fd><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="caret-icon" data-v-0bb349fd><path d="M9,19c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l5.3-5.3L8.3,6.7c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l6,6c0.4,0.4,0.4,1,0,1.4l-6,6C9.5,18.9,9.3,19,9,19z"></path></svg></div></div><div class="items" data-v-0bb349fd><!--[--><div class="VPSidebarItem level-1 is-link" data-v-0bb349fd data-v-0bb349fd><div class="item" data-v-0bb349fd><div class="indicator" data-v-0bb349fd></div><a class="VPLink link link" href="/fe-handbook/document/pages/jsBase/dataType.html" data-v-0bb349fd data-v-f3ed0000><!--[--><p class="text" data-v-0bb349fd>数据类型</p><!--]--><!----></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-0bb349fd data-v-0bb349fd><div class="item" data-v-0bb349fd><div class="indicator" data-v-0bb349fd></div><a class="VPLink link link" href="/fe-handbook/document/pages/jsBase/typeConversion.html" data-v-0bb349fd data-v-f3ed0000><!--[--><p class="text" data-v-0bb349fd>数据类型转换</p><!--]--><!----></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-0bb349fd data-v-0bb349fd><div class="item" data-v-0bb349fd><div class="indicator" data-v-0bb349fd></div><a class="VPLink link link" href="/fe-handbook/document/pages/jsBase/prototype.html" data-v-0bb349fd data-v-f3ed0000><!--[--><p class="text" data-v-0bb349fd>原型与原型链</p><!--]--><!----></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-0bb349fd data-v-0bb349fd><div class="item" data-v-0bb349fd><div class="indicator" data-v-0bb349fd></div><a class="VPLink link link" href="/fe-handbook/document/pages/jsBase/scope.html" data-v-0bb349fd data-v-f3ed0000><!--[--><p class="text" data-v-0bb349fd>闭包</p><!--]--><!----></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-0bb349fd data-v-0bb349fd><div class="item" data-v-0bb349fd><div class="indicator" data-v-0bb349fd></div><a class="VPLink link link" href="/fe-handbook/document/pages/jsBase/this.html" data-v-0bb349fd data-v-f3ed0000><!--[--><p class="text" data-v-0bb349fd>this指针</p><!--]--><!----></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-0bb349fd data-v-0bb349fd><div class="item" data-v-0bb349fd><div class="indicator" data-v-0bb349fd></div><a class="VPLink link link" href="/fe-handbook/document/pages/jsBase/promotion.html" data-v-0bb349fd data-v-f3ed0000><!--[--><p class="text" data-v-0bb349fd>JS中的变量提升和函数提升</p><!--]--><!----></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-0bb349fd data-v-0bb349fd><div class="item" data-v-0bb349fd><div class="indicator" data-v-0bb349fd></div><a class="VPLink link link" href="/fe-handbook/document/pages/jsBase/eventLoop.html" data-v-0bb349fd data-v-f3ed0000><!--[--><p class="text" data-v-0bb349fd>异步&事件循环机制</p><!--]--><!----></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-0bb349fd data-v-0bb349fd><div class="item" data-v-0bb349fd><div class="indicator" data-v-0bb349fd></div><a class="VPLink link link" href="/fe-handbook/document/pages/jsBase/promise.html" data-v-0bb349fd data-v-f3ed0000><!--[--><p class="text" data-v-0bb349fd>promise</p><!--]--><!----></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-0bb349fd data-v-0bb349fd><div class="item" data-v-0bb349fd><div class="indicator" data-v-0bb349fd></div><a class="VPLink link link" href="/fe-handbook/document/pages/jsBase/cookieLocal.html" data-v-0bb349fd data-v-f3ed0000><!--[--><p class="text" data-v-0bb349fd>cookie&local</p><!--]--><!----></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-0bb349fd data-v-0bb349fd><div class="item" data-v-0bb349fd><div class="indicator" data-v-0bb349fd></div><a class="VPLink link link" href="/fe-handbook/document/pages/jsBase/arrayApi.html" data-v-0bb349fd data-v-f3ed0000><!--[--><p class="text" data-v-0bb349fd>arrayApi</p><!--]--><!----></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-0bb349fd data-v-0bb349fd><div class="item" data-v-0bb349fd><div class="indicator" data-v-0bb349fd></div><a class="VPLink link link" href="/fe-handbook/document/pages/jsBase/regular.html" data-v-0bb349fd data-v-f3ed0000><!--[--><p class="text" data-v-0bb349fd>正则</p><!--]--><!----></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-0bb349fd data-v-0bb349fd><div class="item" data-v-0bb349fd><div class="indicator" data-v-0bb349fd></div><a class="VPLink link link" href="/fe-handbook/document/pages/jsBase/coding.html" data-v-0bb349fd data-v-f3ed0000><!--[--><p class="text" data-v-0bb349fd>coding</p><!--]--><!----></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-0bb349fd data-v-0bb349fd><div class="item" data-v-0bb349fd><div class="indicator" data-v-0bb349fd></div><a class="VPLink link link" href="/fe-handbook/document/pages/jsBase/typescript.html" data-v-0bb349fd data-v-f3ed0000><!--[--><p class="text" data-v-0bb349fd>typescript</p><!--]--><!----></a><!----></div><!----></div><!--]--></div></section></div><div class="group" data-v-fe05da0a><section class="VPSidebarItem level-0 collapsible" data-v-fe05da0a data-v-0bb349fd><div class="item" role="button" tabindex="0" data-v-0bb349fd><div class="indicator" data-v-0bb349fd></div><h2 class="text" data-v-0bb349fd>前端综合</h2><div class="caret" role="button" aria-label="toggle section" tabindex="0" data-v-0bb349fd><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="caret-icon" data-v-0bb349fd><path d="M9,19c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l5.3-5.3L8.3,6.7c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l6,6c0.4,0.4,0.4,1,0,1.4l-6,6C9.5,18.9,9.3,19,9,19z"></path></svg></div></div><div class="items" data-v-0bb349fd><!--[--><div class="VPSidebarItem level-1 is-link" data-v-0bb349fd data-v-0bb349fd><div class="item" data-v-0bb349fd><div class="indicator" data-v-0bb349fd></div><a class="VPLink link link" href="/fe-handbook/document/pages/jsBase/eightLeggedEssay.html" data-v-0bb349fd data-v-f3ed0000><!--[--><p class="text" data-v-0bb349fd>前端八股文</p><!--]--><!----></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-0bb349fd data-v-0bb349fd><div class="item" data-v-0bb349fd><div class="indicator" data-v-0bb349fd></div><a class="VPLink link link" href="/fe-handbook/document/pages/jsBase/binary.html" data-v-0bb349fd data-v-f3ed0000><!--[--><p class="text" data-v-0bb349fd>二进制</p><!--]--><!----></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-0bb349fd data-v-0bb349fd><div class="item" data-v-0bb349fd><div class="indicator" data-v-0bb349fd></div><a class="VPLink link link" href="/fe-handbook/document/pages/ssr.html" data-v-0bb349fd data-v-f3ed0000><!--[--><p class="text" data-v-0bb349fd>ssr</p><!--]--><!----></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-0bb349fd data-v-0bb349fd><div class="item" data-v-0bb349fd><div class="indicator" data-v-0bb349fd></div><a class="VPLink link link" href="/fe-handbook/document/pages/webpack.html" data-v-0bb349fd data-v-f3ed0000><!--[--><p class="text" data-v-0bb349fd>webpack</p><!--]--><!----></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-0bb349fd data-v-0bb349fd><div class="item" data-v-0bb349fd><div class="indicator" data-v-0bb349fd></div><a class="VPLink link link" href="/fe-handbook/document/pages/http.html" data-v-0bb349fd data-v-f3ed0000><!--[--><p class="text" data-v-0bb349fd>http</p><!--]--><!----></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-0bb349fd data-v-0bb349fd><div class="item" data-v-0bb349fd><div class="indicator" data-v-0bb349fd></div><a class="VPLink link link" href="/fe-handbook/document/pages/optimize.html" data-v-0bb349fd data-v-f3ed0000><!--[--><p class="text" data-v-0bb349fd>性能优化</p><!--]--><!----></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-0bb349fd data-v-0bb349fd><div class="item" data-v-0bb349fd><div class="indicator" data-v-0bb349fd></div><a class="VPLink link link" href="/fe-handbook/document/pages/xss-csrf.html" data-v-0bb349fd data-v-f3ed0000><!--[--><p class="text" data-v-0bb349fd>xss-csrf</p><!--]--><!----></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-0bb349fd data-v-0bb349fd><div class="item" data-v-0bb349fd><div class="indicator" data-v-0bb349fd></div><a class="VPLink link link" href="/fe-handbook/document/pages/linux.html" data-v-0bb349fd data-v-f3ed0000><!--[--><p class="text" data-v-0bb349fd>linux</p><!--]--><!----></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-0bb349fd data-v-0bb349fd><div class="item" data-v-0bb349fd><div class="indicator" data-v-0bb349fd></div><a class="VPLink link link" href="/fe-handbook/document/pages/nginx.html" data-v-0bb349fd data-v-f3ed0000><!--[--><p class="text" data-v-0bb349fd>nginx</p><!--]--><!----></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-0bb349fd data-v-0bb349fd><div class="item" data-v-0bb349fd><div class="indicator" data-v-0bb349fd></div><a class="VPLink link link" href="/fe-handbook/document/pages/git.html" data-v-0bb349fd data-v-f3ed0000><!--[--><p class="text" data-v-0bb349fd>git管理</p><!--]--><!----></a><!----></div><!----></div><!--]--></div></section></div><div class="group" data-v-fe05da0a><section class="VPSidebarItem level-0 collapsible" data-v-fe05da0a data-v-0bb349fd><div class="item" role="button" tabindex="0" data-v-0bb349fd><div class="indicator" data-v-0bb349fd></div><h2 class="text" data-v-0bb349fd>工作复盘</h2><div class="caret" role="button" aria-label="toggle section" tabindex="0" data-v-0bb349fd><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="caret-icon" data-v-0bb349fd><path d="M9,19c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l5.3-5.3L8.3,6.7c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l6,6c0.4,0.4,0.4,1,0,1.4l-6,6C9.5,18.9,9.3,19,9,19z"></path></svg></div></div><div class="items" data-v-0bb349fd><!--[--><div class="VPSidebarItem level-1 is-link" data-v-0bb349fd data-v-0bb349fd><div class="item" data-v-0bb349fd><div class="indicator" data-v-0bb349fd></div><a class="VPLink link link" href="/fe-handbook/document/pages/workReview/stripe.html" data-v-0bb349fd data-v-f3ed0000><!--[--><p class="text" data-v-0bb349fd>stripe支付体检优化</p><!--]--><!----></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-0bb349fd data-v-0bb349fd><div class="item" data-v-0bb349fd><div class="indicator" data-v-0bb349fd></div><a class="VPLink link link" href="/fe-handbook/document/pages/workReview/interfaceSignatureDesign.html" data-v-0bb349fd data-v-f3ed0000><!--[--><p class="text" data-v-0bb349fd>接口签名设计</p><!--]--><!----></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-0bb349fd data-v-0bb349fd><div class="item" data-v-0bb349fd><div class="indicator" data-v-0bb349fd></div><a class="VPLink link link" href="/fe-handbook/document/pages/workReview/reduxpersistence.html" data-v-0bb349fd data-v-f3ed0000><!--[--><p class="text" data-v-0bb349fd>redux数据持久化</p><!--]--><!----></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-0bb349fd data-v-0bb349fd><div class="item" data-v-0bb349fd><div class="indicator" data-v-0bb349fd></div><a class="VPLink link link" href="/fe-handbook/document/pages/workReview/vuexpersistence.html" data-v-0bb349fd data-v-f3ed0000><!--[--><p class="text" data-v-0bb349fd>vuex数据持久化</p><!--]--><!----></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-0bb349fd data-v-0bb349fd><div class="item" data-v-0bb349fd><div class="indicator" data-v-0bb349fd></div><a class="VPLink link link" href="/fe-handbook/document/pages/workReview/reactSolt.html" data-v-0bb349fd data-v-f3ed0000><!--[--><p class="text" data-v-0bb349fd>react插槽设计</p><!--]--><!----></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-0bb349fd data-v-0bb349fd><div class="item" data-v-0bb349fd><div class="indicator" data-v-0bb349fd></div><a class="VPLink link link" href="/fe-handbook/document/pages/workReview/bigfileUpload.html" data-v-0bb349fd data-v-f3ed0000><!--[--><p class="text" data-v-0bb349fd>大文件上传</p><!--]--><!----></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-0bb349fd data-v-0bb349fd><div class="item" data-v-0bb349fd><div class="indicator" data-v-0bb349fd></div><a class="VPLink link link" href="/fe-handbook/document/pages/workReview/audio.html" data-v-0bb349fd data-v-f3ed0000><!--[--><p class="text" data-v-0bb349fd>音频录制</p><!--]--><!----></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-0bb349fd data-v-0bb349fd><div class="item" data-v-0bb349fd><div class="indicator" data-v-0bb349fd></div><a class="VPLink link link" href="/fe-handbook/document/pages/workReview/virtuaLlist.html" data-v-0bb349fd data-v-f3ed0000><!--[--><p class="text" data-v-0bb349fd>虚拟列表</p><!--]--><!----></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-0bb349fd data-v-0bb349fd><div class="item" data-v-0bb349fd><div class="indicator" data-v-0bb349fd></div><a class="VPLink link link" href="/fe-handbook/document/pages/workReview/imageCroppingCompression.html" data-v-0bb349fd data-v-f3ed0000><!--[--><p class="text" data-v-0bb349fd>图片裁剪&压缩</p><!--]--><!----></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-0bb349fd data-v-0bb349fd><div class="item" data-v-0bb349fd><div class="indicator" data-v-0bb349fd></div><a class="VPLink link link" href="/fe-handbook/document/pages/workReview/axiosPackaging.html" data-v-0bb349fd data-v-f3ed0000><!--[--><p class="text" data-v-0bb349fd>axios封装</p><!--]--><!----></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-0bb349fd data-v-0bb349fd><div class="item" data-v-0bb349fd><div class="indicator" data-v-0bb349fd></div><a class="VPLink link link" href="/fe-handbook/document/pages/workReview/monitor.html" data-v-0bb349fd data-v-f3ed0000><!--[--><p class="text" data-v-0bb349fd>前端监控SDK</p><!--]--><!----></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-0bb349fd data-v-0bb349fd><div class="item" data-v-0bb349fd><div class="indicator" data-v-0bb349fd></div><a class="VPLink link link" href="/fe-handbook/document/pages/workReview/ImagedragVerification.html" data-v-0bb349fd data-v-f3ed0000><!--[--><p class="text" data-v-0bb349fd>图片拖动验证</p><!--]--><!----></a><!----></div><!----></div><!--]--></div></section></div><div class="group" data-v-fe05da0a><section class="VPSidebarItem level-0 collapsible" data-v-fe05da0a data-v-0bb349fd><div class="item" role="button" tabindex="0" data-v-0bb349fd><div class="indicator" data-v-0bb349fd></div><h2 class="text" data-v-0bb349fd>html/css</h2><div class="caret" role="button" aria-label="toggle section" tabindex="0" data-v-0bb349fd><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="caret-icon" data-v-0bb349fd><path d="M9,19c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l5.3-5.3L8.3,6.7c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l6,6c0.4,0.4,0.4,1,0,1.4l-6,6C9.5,18.9,9.3,19,9,19z"></path></svg></div></div><div class="items" data-v-0bb349fd><!--[--><div class="VPSidebarItem level-1 is-link" data-v-0bb349fd data-v-0bb349fd><div class="item" data-v-0bb349fd><div class="indicator" data-v-0bb349fd></div><a class="VPLink link link" href="/fe-handbook/document/pages/htmlCss/boxModel.html" data-v-0bb349fd data-v-f3ed0000><!--[--><p class="text" data-v-0bb349fd>盒模型</p><!--]--><!----></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-0bb349fd data-v-0bb349fd><div class="item" data-v-0bb349fd><div class="indicator" data-v-0bb349fd></div><a class="VPLink link link" href="/fe-handbook/document/pages/htmlCss/margin.html" data-v-0bb349fd data-v-f3ed0000><!--[--><p class="text" data-v-0bb349fd>margin重叠</p><!--]--><!----></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-0bb349fd data-v-0bb349fd><div class="item" data-v-0bb349fd><div class="indicator" data-v-0bb349fd></div><a class="VPLink link link" href="/fe-handbook/document/pages/htmlCss/bfc.html" data-v-0bb349fd data-v-f3ed0000><!--[--><p class="text" data-v-0bb349fd>bfc</p><!--]--><!----></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-0bb349fd data-v-0bb349fd><div class="item" data-v-0bb349fd><div class="indicator" data-v-0bb349fd></div><a class="VPLink link link" href="/fe-handbook/document/pages/htmlCss/layout.html" data-v-0bb349fd data-v-f3ed0000><!--[--><p class="text" data-v-0bb349fd>圣杯布局&双飞翼布局</p><!--]--><!----></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-0bb349fd data-v-0bb349fd><div class="item" data-v-0bb349fd><div class="indicator" data-v-0bb349fd></div><a class="VPLink link link" href="/fe-handbook/document/pages/htmlCss/dice.html" data-v-0bb349fd data-v-f3ed0000><!--[--><p class="text" data-v-0bb349fd>flex画骰子</p><!--]--><!----></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-0bb349fd data-v-0bb349fd><div class="item" data-v-0bb349fd><div class="indicator" data-v-0bb349fd></div><a class="VPLink link link" href="/fe-handbook/document/pages/htmlCss/position.html" data-v-0bb349fd data-v-f3ed0000><!--[--><p class="text" data-v-0bb349fd>position定位</p><!--]--><!----></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-0bb349fd data-v-0bb349fd><div class="item" data-v-0bb349fd><div class="indicator" data-v-0bb349fd></div><a class="VPLink link link" href="/fe-handbook/document/pages/htmlCss/align.html" data-v-0bb349fd data-v-f3ed0000><!--[--><p class="text" data-v-0bb349fd>对齐</p><!--]--><!----></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-0bb349fd data-v-0bb349fd><div class="item" data-v-0bb349fd><div class="indicator" data-v-0bb349fd></div><a class="VPLink link link" href="/fe-handbook/document/pages/htmlCss/rem-em-vw.html" data-v-0bb349fd data-v-f3ed0000><!--[--><p class="text" data-v-0bb349fd>rem-em-vw</p><!--]--><!----></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-0bb349fd data-v-0bb349fd><div class="item" data-v-0bb349fd><div class="indicator" data-v-0bb349fd></div><a class="VPLink link link" href="/fe-handbook/document/pages/htmlCss/grid.html" data-v-0bb349fd data-v-f3ed0000><!--[--><p class="text" data-v-0bb349fd>grid布局</p><!--]--><!----></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-0bb349fd data-v-0bb349fd><div class="item" data-v-0bb349fd><div class="indicator" data-v-0bb349fd></div><a class="VPLink link link" href="/fe-handbook/document/pages/htmlCss/htmlCss.html" data-v-0bb349fd data-v-f3ed0000><!--[--><p class="text" data-v-0bb349fd>htmlCss总结</p><!--]--><!----></a><!----></div><!----></div><!--]--></div></section></div><!--]--><!--[--><!--]--></nav></aside><div class="VPContent has-sidebar" id="VPContent" data-v-bffce215 data-v-91952ce3><div class="VPDoc has-sidebar has-aside" data-v-91952ce3 data-v-c11df1f0><!--[--><!--]--><div class="container" data-v-c11df1f0><div class="aside" data-v-c11df1f0><div class="aside-curtain" data-v-c11df1f0></div><div class="aside-container" data-v-c11df1f0><div class="aside-content" data-v-c11df1f0><div class="VPDocAside" data-v-c11df1f0 data-v-cb998dce><!--[--><!--]--><!--[--><!--]--><div class="VPDocAsideOutline" data-v-cb998dce data-v-c834746b><div class="content" data-v-c834746b><div class="outline-marker" data-v-c834746b></div><div class="outline-title" data-v-c834746b>On this page</div><nav aria-labelledby="doc-outline-aria-label" data-v-c834746b><span class="visually-hidden" id="doc-outline-aria-label" data-v-c834746b> Table of Contents for current page </span><ul class="root" data-v-c834746b data-v-a379eb72><!--[--><!--]--></ul></nav></div></div><!--[--><!--]--><div class="spacer" data-v-cb998dce></div><!--[--><!--]--><!----><!--[--><!--]--><!--[--><!--]--></div></div></div></div><div class="content" data-v-c11df1f0><div class="content-container" data-v-c11df1f0><!--[--><!--]--><!----><main class="main" data-v-c11df1f0><div style="position:relative;" class="vp-doc _fe-handbook_document_pages_vue_vue3_0" data-v-c11df1f0><div><h1 id="vue3-0" tabindex="-1">vue3.0 <a class="header-anchor" href="#vue3-0" aria-label="Permalink to &quot;vue3.0&quot;">​</a></h1><ul><li><a href="https://gitee.com/hl-fe/fe-handbook/tree/master/code/vue3.0" target="_blank">源码实现地址</a></li></ul><h2 id="vue2-3-区别" tabindex="-1">vue2/3 区别 <a class="header-anchor" href="#vue2-3-区别" aria-label="Permalink to &quot;vue2/3 区别&quot;">​</a></h2><ul><li>项目架构上做对比 Vue3采用 <code>monorepo</code> 的方式可以让一个项目下管理多个项目，每个包可以单独发布和使用</li><li>Vue3 基于 TS compositionApi tree-shaking 支持比较友好， OptionsApi 缺陷就是不能 tree-shaking</li><li>Vue2 后期引入 RFC , 使每个版本改动可控 rfcs</li></ul><h2 id="vue3-内部代码优化" tabindex="-1">vue3 内部代码优化 <a class="header-anchor" href="#vue3-内部代码优化" aria-label="Permalink to &quot;vue3 内部代码优化&quot;">​</a></h2><ul><li>Vue3 劫持数据采用 Es6 proxy，Vue2 劫持数据采用 defineProperty。 <ul><li>defineProperty 有性能问题和缺陷，初始化时会递归遍历每一个属性加 set，get 拦截，Vue3 在取值的时候才会进行递归</li></ul></li><li>Vue3 中对模板编译进行了优化，编译时 生成了 Block tree，可以对子节点的动态节点进行收集，可以减少比较，并且采用了 patchFlag 标记动态节点</li><li>Vue3 中 采用了 compositionApi 实现了方便代码的复用 （解决了 mixin 的问题- 命名冲突 数据来源不明确）</li><li>Vue3 diff 算法 内部用的是 最长递增子序列 + 暴力的递归比对 （全量比对浪费性能)</li><li>增加了 Fragment,Teleport，Suspense 组件</li></ul><h2 id="生命周期" tabindex="-1">生命周期 <a class="header-anchor" href="#生命周期" aria-label="Permalink to &quot;生命周期&quot;">​</a></h2><div class="language-js"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">vue2           </span><span style="color:#89DDFF;">-------&gt;</span><span style="color:#A6ACCD;">      vue3</span></span>
<span class="line"><span style="color:#A6ACCD;"> </span></span>
<span class="line"><span style="color:#A6ACCD;">beforeCreate   </span><span style="color:#89DDFF;">--------&gt;</span><span style="color:#A6ACCD;">      </span><span style="color:#82AAFF;">setup</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">()</span><span style="color:#C792EA;">=&gt;</span><span style="color:#89DDFF;">{}</span><span style="color:#A6ACCD;">)</span></span>
<span class="line"><span style="color:#A6ACCD;">created        </span><span style="color:#89DDFF;">--------&gt;</span><span style="color:#A6ACCD;">      </span><span style="color:#82AAFF;">setup</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">()</span><span style="color:#C792EA;">=&gt;</span><span style="color:#89DDFF;">{}</span><span style="color:#A6ACCD;">)</span></span>
<span class="line"><span style="color:#A6ACCD;">beforeMount    </span><span style="color:#89DDFF;">--------&gt;</span><span style="color:#A6ACCD;">      </span><span style="color:#82AAFF;">onBeforeMount</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">()</span><span style="color:#C792EA;">=&gt;</span><span style="color:#89DDFF;">{}</span><span style="color:#A6ACCD;">)</span></span>
<span class="line"><span style="color:#A6ACCD;">mounted        </span><span style="color:#89DDFF;">--------&gt;</span><span style="color:#A6ACCD;">      </span><span style="color:#82AAFF;">onMounted</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">()</span><span style="color:#C792EA;">=&gt;</span><span style="color:#89DDFF;">{}</span><span style="color:#A6ACCD;">)</span></span>
<span class="line"><span style="color:#A6ACCD;">beforeUpdate   </span><span style="color:#89DDFF;">--------&gt;</span><span style="color:#A6ACCD;">      </span><span style="color:#82AAFF;">onBeforeUpdate</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">()</span><span style="color:#C792EA;">=&gt;</span><span style="color:#89DDFF;">{}</span><span style="color:#A6ACCD;">)</span></span>
<span class="line"><span style="color:#A6ACCD;">updated        </span><span style="color:#89DDFF;">--------&gt;</span><span style="color:#A6ACCD;">      </span><span style="color:#82AAFF;">onUpdated</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">()</span><span style="color:#C792EA;">=&gt;</span><span style="color:#89DDFF;">{}</span><span style="color:#A6ACCD;">)</span></span>
<span class="line"><span style="color:#A6ACCD;">beforeDestroy  </span><span style="color:#89DDFF;">--------&gt;</span><span style="color:#A6ACCD;">      </span><span style="color:#82AAFF;">onBeforeUnmount</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">()</span><span style="color:#C792EA;">=&gt;</span><span style="color:#89DDFF;">{}</span><span style="color:#A6ACCD;">)</span></span>
<span class="line"><span style="color:#A6ACCD;">destroyed      </span><span style="color:#89DDFF;">--------&gt;</span><span style="color:#A6ACCD;">      </span><span style="color:#82AAFF;">onUnmounted</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">()</span><span style="color:#C792EA;">=&gt;</span><span style="color:#89DDFF;">{}</span><span style="color:#A6ACCD;">)</span></span>
<span class="line"><span style="color:#A6ACCD;">activated      </span><span style="color:#89DDFF;">--------&gt;</span><span style="color:#A6ACCD;">      </span><span style="color:#82AAFF;">onActivated</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">()</span><span style="color:#C792EA;">=&gt;</span><span style="color:#89DDFF;">{}</span><span style="color:#A6ACCD;">)</span></span>
<span class="line"><span style="color:#A6ACCD;">deactivated    </span><span style="color:#89DDFF;">--------&gt;</span><span style="color:#A6ACCD;">      </span><span style="color:#82AAFF;">onDeactivated</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">()</span><span style="color:#C792EA;">=&gt;</span><span style="color:#89DDFF;">{}</span><span style="color:#A6ACCD;">)</span></span>
<span class="line"><span style="color:#A6ACCD;">errorCaptured  </span><span style="color:#89DDFF;">--------&gt;</span><span style="color:#A6ACCD;">      </span><span style="color:#82AAFF;">onErrorCaptured</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">()</span><span style="color:#C792EA;">=&gt;</span><span style="color:#89DDFF;">{}</span><span style="color:#A6ACCD;">)</span></span></code></pre></div><h2 id="vue-渲染流程" tabindex="-1">Vue 渲染流程 <a class="header-anchor" href="#vue-渲染流程" aria-label="Permalink to &quot;Vue 渲染流程&quot;">​</a></h2><ul><li>1、当在调用 createApp首次渲染时，会执行 runtime-core 模块中的 createRenderer 渲染器，并且返回一个渲染对象</li><li>2、调用 mount 获取根容器并且清空所有的节点，进行挂载，根据rootComponent 创建vnode，调用 patch 函数进行渲染</li><li>3、如果是组件类型，根据VNode创建组件实例，<code>处理setup 函数</code></li><li>4、如果有 setup 函数，<code>执行结果是一个函数</code>作为 render渲染函数(变成虚拟节点)</li><li>5、如果没有 setup 函数，或者setup 函数<code>执行结果不是函数</code>，需要将 template 变成 render 函数 compileToFunctions()</li><li>4、此时会创建一个渲染的effect，将渲染和更新的流程交给effect处理</li><li>5、effect 在执行时，会调用组件实例的 <code>render 函数将模版转换成Vnode</code>，如果此时<code>Vnode中</code>有<code>reactive&amp;ref</code>取值操作会触发 Proxy 执行<code>track</code>收集副作用</li><li>6、当数据发生变化后，会通过<code>trigger</code>通知 effect 重新执行渲染组件</li></ul><h3 id="vue-reactive-数据响应式处理" tabindex="-1">Vue reactive 数据响应式处理 <a class="header-anchor" href="#vue-reactive-数据响应式处理" aria-label="Permalink to &quot;Vue reactive 数据响应式处理&quot;">​</a></h3><ul><li>reactive 是利用 ES6 的 proxy 加上发布、订阅来处理响应式数据</li><li>1、reactive 在初始化时，首先被判断是不是对象，不是对象就直接返回</li><li>2、如果已经被<code>reactive</code>代理过了，直接返回代理对象</li><li>3、如果该对象已经被缓存过，直接取缓存的结果返回</li><li>4、如果以上都未命中，创建 Proxy 代理对象，并且进行缓存</li></ul><div class="language-js"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#C792EA;">function</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">createReactiveObject</span><span style="color:#89DDFF;">(</span></span>
<span class="line"><span style="color:#A6ACCD;">  </span><span style="color:#A6ACCD;font-style:italic;">target</span><span style="color:#89DDFF;">,</span></span>
<span class="line"><span style="color:#A6ACCD;">  </span><span style="color:#A6ACCD;font-style:italic;">isReadonly</span><span style="color:#89DDFF;">,</span></span>
<span class="line"><span style="color:#A6ACCD;">  </span><span style="color:#A6ACCD;font-style:italic;">baseHandlers</span><span style="color:#89DDFF;">,</span></span>
<span class="line"><span style="color:#A6ACCD;">  </span><span style="color:#A6ACCD;font-style:italic;">proxyMap</span><span style="color:#89DDFF;">,</span></span>
<span class="line"><span style="color:#89DDFF;">)</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;font-style:italic;">if</span><span style="color:#F07178;"> ( </span><span style="color:#89DDFF;">!</span><span style="color:#82AAFF;">isObject</span><span style="color:#F07178;">( </span><span style="color:#A6ACCD;">target</span><span style="color:#F07178;"> ) ) </span><span style="color:#89DDFF;">{</span><span style="color:#F07178;"> </span><span style="color:#676E95;font-style:italic;">// 不是对象就直接跳过</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#89DDFF;font-style:italic;">return</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">target</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#89DDFF;">  </span><span style="color:#676E95;font-style:italic;">// 如果已经被代理过了，直接返回</span></span>
<span class="line"><span style="color:#89DDFF;">  </span><span style="color:#676E95;font-style:italic;">// reactive(reactive(obj))</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;font-style:italic;">if</span><span style="color:#F07178;"> (</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#A6ACCD;">target</span><span style="color:#F07178;">[</span><span style="color:#A6ACCD;">ReactiveFlags</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">RAW</span><span style="color:#F07178;">] </span><span style="color:#89DDFF;">&amp;&amp;</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#89DDFF;">!</span><span style="color:#F07178;">( </span><span style="color:#A6ACCD;">isReadonly</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">&amp;&amp;</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">target</span><span style="color:#F07178;">[</span><span style="color:#A6ACCD;">ReactiveFlags</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">IS_REACTIVE</span><span style="color:#F07178;">] )</span></span>
<span class="line"><span style="color:#F07178;">  ) </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#89DDFF;font-style:italic;">return</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">target</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#89DDFF;">  </span><span style="color:#676E95;font-style:italic;">// 如果某一个对象已经被代理过，下次在进行代理，直接取缓存的结果</span></span>
<span class="line"><span style="color:#89DDFF;">  </span><span style="color:#676E95;font-style:italic;">// let obj = { name: &quot;hulei&quot; };</span></span>
<span class="line"><span style="color:#89DDFF;">  </span><span style="color:#676E95;font-style:italic;">// let state = reactive( obj );</span></span>
<span class="line"><span style="color:#89DDFF;">  </span><span style="color:#676E95;font-style:italic;">// reactive( obj );</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#C792EA;">const</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">existingProxy</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">proxyMap</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">get</span><span style="color:#F07178;">( </span><span style="color:#A6ACCD;">target</span><span style="color:#F07178;"> ) </span><span style="color:#676E95;font-style:italic;">// 看目标是否被代理过</span></span>
<span class="line"><span style="color:#89DDFF;">  </span><span style="color:#676E95;font-style:italic;">// 如果代理过，直接返回代理过的对象</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;font-style:italic;">if</span><span style="color:#F07178;"> ( </span><span style="color:#A6ACCD;">existingProxy</span><span style="color:#F07178;"> ) </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#89DDFF;font-style:italic;">return</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">existingProxy</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#89DDFF;">  </span><span style="color:#676E95;font-style:italic;">// 创建代理对象</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#C792EA;">let</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">proxy</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">new</span><span style="color:#F07178;"> </span><span style="color:#82AAFF;">Proxy</span><span style="color:#F07178;">( </span><span style="color:#A6ACCD;">target</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">baseHandlers</span><span style="color:#F07178;"> )</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#A6ACCD;">proxyMap</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">set</span><span style="color:#F07178;">( </span><span style="color:#A6ACCD;">target</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">proxy</span><span style="color:#F07178;"> ) </span><span style="color:#676E95;font-style:italic;">// 存到缓存中</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;font-style:italic;">return</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">proxy</span></span>
<span class="line"></span>
<span class="line"><span style="color:#89DDFF;">}</span></span></code></pre></div><h3 id="取值-订阅-get" tabindex="-1">取值/订阅 get <a class="header-anchor" href="#取值-订阅-get" aria-label="Permalink to &quot;取值/订阅 get&quot;">​</a></h3><ul><li>1、reactive 在取值时，会触发 get 操作，执行<code>track</code>让当前的对象的属性，去收集渲染的 effect</li><li>2、如果取出的值时一个对象，需要继续走 reactive 做代理</li><li>3、如果是数组 includes, indexOf, lastIndexOf 会被拦截，并且让数组的每一项索引去收集 effect</li></ul><h3 id="设置-发布-set" tabindex="-1">设置/发布 set <a class="header-anchor" href="#设置-发布-set" aria-label="Permalink to &quot;设置/发布 set&quot;">​</a></h3><ul><li>1、reactive 数据在发生变化时，会触发 set 操作，执行<code>trigger</code>通知对应的 effect 更新视图</li><li>2、如果是数组比较特殊，因为数组在 push 操作是，会触发二次 set 拦截，<code>第一次会给新的索引位置,新增一个值</code> <code>第二次改变数组的length的长度(会被屏蔽掉)</code></li><li>3、当数组在 push 操作的时候，会触发 set 操作，因为<code>索引是新加的</code>，没有依赖收集过，所以需要通过数组的 length 触发 effect 更新视图</li></ul><h2 id="vue2-vs-vue3-代理对比" tabindex="-1">vue2 vs vue3 代理对比 <a class="header-anchor" href="#vue2-vs-vue3-代理对比" aria-label="Permalink to &quot;vue2 vs vue3 代理对比&quot;">​</a></h2><ul><li>vue3 针对的是对象来进行劫持，不用改写原来的对象，如果是嵌套，当取值的时候才会代理</li><li>vue3 可以对不存在的属性进行获取，也会走 get 方法，Proxy 支持数组</li><li>vue2 针对的是属性劫持，改写了原来对象，一上来就递归的</li><li>懒递归 当我们取值的时候才去做递归代理，如果不取默认值代理一层</li></ul><h2 id="ref-可以让一个普通值具备响应式的能力-如果是一个对象还是利用的-reactive" tabindex="-1">ref(可以让一个普通值具备响应式的能力，如果是一个对象还是利用的 reactive) <a class="header-anchor" href="#ref-可以让一个普通值具备响应式的能力-如果是一个对象还是利用的-reactive" aria-label="Permalink to &quot;ref(可以让一个普通值具备响应式的能力，如果是一个对象还是利用的 reactive)&quot;">​</a></h2><ul><li><p>ref 是一个类在实例化时会存储原始的值，通过<code>属性访问器</code> set、get 来实现响应式的能力</p></li><li><p>当在取 state.value 时，触发 get 让当前的实例去收集 effect</p></li><li><p>当在给 value 赋值时，会触发 set 拦截通知 effect 触发更新</p></li><li><p>1、ref 内部是通过属性访问器来实现的，在初始化时会通过 createRef 创建 Ref 实例，会把原始的值存储在当前实例上，返回当前的 Ref 实例对象</p></li><li><p>2、当在访问实例上的 value 属性时(xxx.value)，会触发依赖收集，并且返回原始的值</p></li><li><p>3、当在给 value 赋值时,如果值不等同，会触发当前的依赖执行，并且赋值给原始的值</p></li></ul><div class="language-js"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#C792EA;">const</span><span style="color:#A6ACCD;"> convert </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;"> </span><span style="color:#A6ACCD;font-style:italic;">v</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">)</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">=&gt;</span><span style="color:#A6ACCD;"> ( </span><span style="color:#82AAFF;">isObject</span><span style="color:#A6ACCD;">( v ) </span><span style="color:#89DDFF;">?</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">reactive</span><span style="color:#A6ACCD;">( v ) </span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> v )</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#C792EA;">class</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">RefImpl</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">  </span><span style="color:#C792EA;">public</span><span style="color:#A6ACCD;"> </span><span style="color:#F07178;">_value</span><span style="color:#89DDFF;">;</span><span style="color:#A6ACCD;"> </span><span style="color:#676E95;font-style:italic;">// 原始的值</span></span>
<span class="line"><span style="color:#A6ACCD;">  </span><span style="color:#C792EA;">public</span><span style="color:#A6ACCD;"> </span><span style="color:#F07178;">__v_isRef</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#FF9CAC;">true</span><span style="color:#89DDFF;">;</span><span style="color:#A6ACCD;"> </span><span style="color:#676E95;font-style:italic;">// 表示他是一个ref</span></span>
<span class="line"><span style="color:#A6ACCD;">  </span><span style="color:#C792EA;">constructor</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">public</span><span style="color:#A6ACCD;"> </span><span style="color:#A6ACCD;font-style:italic;">rawValue</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#A6ACCD;font-style:italic;">shallow</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">)</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#89DDFF;">    </span><span style="color:#676E95;font-style:italic;">// 如果不是浅的，并且是对象，走reactive代理拿到结果</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#89DDFF;">this.</span><span style="color:#A6ACCD;">_value</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">shallow</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">?</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">this.</span><span style="color:#A6ACCD;">rawValue</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">:</span><span style="color:#F07178;"> </span><span style="color:#82AAFF;">convert</span><span style="color:#F07178;">( </span><span style="color:#89DDFF;">this.</span><span style="color:#A6ACCD;">rawValue</span><span style="color:#F07178;"> )</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#A6ACCD;">  </span><span style="color:#C792EA;">get</span><span style="color:#A6ACCD;"> </span><span style="color:#F07178;">value</span><span style="color:#89DDFF;">()</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#82AAFF;">track</span><span style="color:#F07178;">( </span><span style="color:#89DDFF;">this,</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">TrackOpTypes</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">GET</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">value</span><span style="color:#89DDFF;">&quot;</span><span style="color:#F07178;"> )</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#89DDFF;font-style:italic;">return</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">this.</span><span style="color:#A6ACCD;">_value</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#A6ACCD;">  </span><span style="color:#C792EA;">set</span><span style="color:#A6ACCD;"> </span><span style="color:#F07178;">value</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;"> </span><span style="color:#A6ACCD;font-style:italic;">newValue</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">)</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#89DDFF;font-style:italic;">if</span><span style="color:#F07178;"> ( </span><span style="color:#82AAFF;">hasChanged</span><span style="color:#F07178;">( </span><span style="color:#89DDFF;">this.</span><span style="color:#A6ACCD;">rawValue</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">newValue</span><span style="color:#F07178;"> ) ) </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">      </span><span style="color:#89DDFF;">this.</span><span style="color:#A6ACCD;">rawValue</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">newValue</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#F07178;">      </span><span style="color:#89DDFF;">this.</span><span style="color:#A6ACCD;">_value</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">newValue</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#F07178;">      </span><span style="color:#82AAFF;">trigger</span><span style="color:#F07178;">( </span><span style="color:#89DDFF;">this,</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">TriggerOrTypes</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">UPDATE</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">value</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">newValue</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">this.</span><span style="color:#A6ACCD;">rawValue</span><span style="color:#F07178;"> )</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> createRef </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;"> </span><span style="color:#A6ACCD;font-style:italic;">value</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#A6ACCD;font-style:italic;">shallow</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">)</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">=&gt;</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;font-style:italic;">return</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">new</span><span style="color:#F07178;"> </span><span style="color:#82AAFF;">RefImpl</span><span style="color:#F07178;">( </span><span style="color:#A6ACCD;">value</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">shallow</span><span style="color:#F07178;"> )</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;">// 可以把普通值变成响应式数据</span></span>
<span class="line"><span style="color:#C792EA;">function</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">ref</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;"> </span><span style="color:#A6ACCD;font-style:italic;">value</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">)</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;font-style:italic;">return</span><span style="color:#F07178;"> </span><span style="color:#82AAFF;">createRef</span><span style="color:#F07178;">( </span><span style="color:#A6ACCD;">value</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> </span><span style="color:#FF9CAC;">false</span><span style="color:#F07178;"> )</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span></code></pre></div><h2 id="ref-和-reactive-的区别" tabindex="-1">ref 和 reactive 的区别 <a class="header-anchor" href="#ref-和-reactive-的区别" aria-label="Permalink to &quot;ref 和 reactive 的区别&quot;">​</a></h2><ul><li><p>ref</p><blockquote><p>1、ref 可以让<code>普通的值</code>具备响应式的能力</p></blockquote><blockquote><p>2、ref 是通过属性访问器 get、set 拦截处理更新</p></blockquote></li><li><p>reactive</p><blockquote><p>reactive 只能代理对象，并且使用的 Es6 的 Proxy</p></blockquote></li></ul><h2 id="toref-作用" tabindex="-1">toRef 作用 <a class="header-anchor" href="#toref-作用" aria-label="Permalink to &quot;toRef 作用&quot;">​</a></h2><ul><li><p>toRef 可以解析取出 reactive 某一个属性，并且不会失去响应式的能力<code>(也是利用属性访问器)</code></p></li><li><p>toRef 是一个类在实例化时会<code>存储原始的 target,key</code></p></li><li><p>当在取 state.value 时，触发 get 取<code>原始的值</code></p></li><li><p>当在给 value 赋值时，会触发 set 给<code>原始的值赋值</code></p></li></ul><div class="language-js"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> state </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">reactive</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">{</span><span style="color:#A6ACCD;"> </span><span style="color:#F07178;">name</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">hulei</span><span style="color:#89DDFF;">&quot;</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">}</span><span style="color:#A6ACCD;">)</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;">// 对象直接解析会失去响应式</span></span>
<span class="line"><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span><span style="color:#A6ACCD;"> name </span><span style="color:#89DDFF;">}</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> state</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;">// 通过toRef会通过get、set代理的方式去访问原对象上的属性，不会失去响应式的特性</span></span>
<span class="line"><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> userName </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">toRef</span><span style="color:#A6ACCD;">(state</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">name</span><span style="color:#89DDFF;">&quot;</span><span style="color:#A6ACCD;">)</span><span style="color:#89DDFF;">;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#A6ACCD;">console</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">log</span><span style="color:#A6ACCD;">(userName</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">value)</span><span style="color:#89DDFF;">;</span></span></code></pre></div><h2 id="torefs" tabindex="-1">toRefs <a class="header-anchor" href="#torefs" aria-label="Permalink to &quot;toRefs&quot;">​</a></h2><ul><li>toRefs 底层是调用的 toRef，给每一个属性绑定一个 toRef，实现同时结构多个值</li></ul><div class="language-js"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#89DDFF;font-style:italic;">import</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">reactive</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">toRefs</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">}</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;font-style:italic;">from</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">vue</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#89DDFF;font-style:italic;">export</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;font-style:italic;">default</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">  </span><span style="color:#F07178;">setup</span><span style="color:#89DDFF;">()</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#C792EA;">const</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">user</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#82AAFF;">reactive</span><span style="color:#F07178;">(</span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">      name</span><span style="color:#89DDFF;">:</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">hu.lei</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">,</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#89DDFF;">}</span><span style="color:#F07178;">)</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#89DDFF;">    </span><span style="color:#676E95;font-style:italic;">// 如果不通过toRefs会失去响应式的能力</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#89DDFF;font-style:italic;">return</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">      </span><span style="color:#89DDFF;">...</span><span style="color:#82AAFF;">toRefs</span><span style="color:#F07178;">(</span><span style="color:#A6ACCD;">user</span><span style="color:#F07178;">)</span><span style="color:#89DDFF;">,</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#89DDFF;">};</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;">},</span></span>
<span class="line"><span style="color:#89DDFF;">};</span></span></code></pre></div><div class="language-js"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#89DDFF;font-style:italic;">export</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">function</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">toRef</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;font-style:italic;">targat</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#A6ACCD;font-style:italic;">key</span><span style="color:#89DDFF;">)</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;font-style:italic;">return</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">new</span><span style="color:#F07178;"> </span><span style="color:#82AAFF;">ObjectRefImpl</span><span style="color:#F07178;">(</span><span style="color:#A6ACCD;">targat</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">key</span><span style="color:#F07178;">)</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#C792EA;">class</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">ObjectRefImpl</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">  </span><span style="color:#C792EA;">public</span><span style="color:#A6ACCD;"> </span><span style="color:#F07178;">__v_isRef</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#FF9CAC;">true</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#A6ACCD;">  </span><span style="color:#C792EA;">constructor</span><span style="color:#89DDFF;">(</span><span style="color:#C792EA;">public</span><span style="color:#A6ACCD;"> </span><span style="color:#A6ACCD;font-style:italic;">targat</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">public</span><span style="color:#A6ACCD;"> </span><span style="color:#A6ACCD;font-style:italic;">key</span><span style="color:#89DDFF;">)</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#A6ACCD;">  </span><span style="color:#C792EA;">get</span><span style="color:#A6ACCD;"> </span><span style="color:#F07178;">value</span><span style="color:#89DDFF;">()</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#89DDFF;font-style:italic;">return</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">this.</span><span style="color:#A6ACCD;">targat</span><span style="color:#F07178;">[</span><span style="color:#89DDFF;">this.</span><span style="color:#A6ACCD;">key</span><span style="color:#F07178;">]</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#A6ACCD;">  </span><span style="color:#C792EA;">set</span><span style="color:#A6ACCD;"> </span><span style="color:#F07178;">value</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;font-style:italic;">value</span><span style="color:#89DDFF;">)</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#89DDFF;">this.</span><span style="color:#A6ACCD;">targat</span><span style="color:#F07178;">[</span><span style="color:#89DDFF;">this.</span><span style="color:#A6ACCD;">key</span><span style="color:#F07178;">] </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">value</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#89DDFF;font-style:italic;">export</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">function</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">toRefs</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;font-style:italic;">targat</span><span style="color:#89DDFF;">)</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#C792EA;">let</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">res</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#82AAFF;">isArray</span><span style="color:#F07178;">(</span><span style="color:#A6ACCD;">targat</span><span style="color:#F07178;">) </span><span style="color:#89DDFF;">?</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">new</span><span style="color:#F07178;"> </span><span style="color:#82AAFF;">Array</span><span style="color:#F07178;">(</span><span style="color:#A6ACCD;">targat</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">length</span><span style="color:#F07178;">) </span><span style="color:#89DDFF;">:</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">{};</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;font-style:italic;">for</span><span style="color:#F07178;"> (</span><span style="color:#C792EA;">const</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">key</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">in</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">targat</span><span style="color:#F07178;">) </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#A6ACCD;">res</span><span style="color:#F07178;">[</span><span style="color:#A6ACCD;">key</span><span style="color:#F07178;">] </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#82AAFF;">toRef</span><span style="color:#F07178;">(</span><span style="color:#A6ACCD;">targat</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">key</span><span style="color:#F07178;">)</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;font-style:italic;">return</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">res</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span></code></pre></div><h2 id="effect-渲染的-effect、计算属性的-effect、watch-effect" tabindex="-1">effect(渲染的 effect、计算属性的 effect、watch effect) <a class="header-anchor" href="#effect-渲染的-effect、计算属性的-effect、watch-effect" aria-label="Permalink to &quot;effect(渲染的 effect、计算属性的 effect、watch effect)&quot;">​</a></h2><ul><li><p>渲染的 effect</p><blockquote><p>1、组件在挂载的时候，会把渲染的控制权交给 effect</p></blockquote><blockquote><p>2、组件在渲染的时候，会调用 render 生成 Vnode,如果有取值操作，会触发 get 拦截，收集当前的 effect</p></blockquote><blockquote><p>3、当响应式数据发生变化时，会触发 set 通知 effect 更新视图</p></blockquote></li><li><p>watch effect</p><blockquote><p>1、在调用 watch 时，首先会进行取值，取值的时候会收集 watch effect</p></blockquote><blockquote><p>2、当响应式数据发生变化时，会触发 set 通知 watch effect 执行监听的回调</p></blockquote></li></ul><h2 id="vue-watch、watcheffect-监听" tabindex="-1">Vue watch、watchEffect 监听 <a class="header-anchor" href="#vue-watch、watcheffect-监听" aria-label="Permalink to &quot;Vue watch、watchEffect 监听&quot;">​</a></h2><ul><li>1、watch 在初始化时，会执行<code>doWatch</code>，<code>构建一个 effect</code>，将控制权交给 effect</li><li>2、effect会立马执行<code>watch函数</code>获取到监听的值，<code>在取值的时候</code>会触发 get,收集当前的 effect</li><li>3、当响应式数据发生变化时，会触发 set 通知 effect 执行自定义的<code>schedular函数中的</code>watch监听的回调`</li><li>4、effect 更新时异步的，一个值同步修改多次，只会执行一次更新，利用事件循环机制</li></ul><h3 id="watcheffect" tabindex="-1">watchEffect <a class="header-anchor" href="#watcheffect" aria-label="Permalink to &quot;watchEffect&quot;">​</a></h3><ul><li>watchEffect 没有监听的回调</li><li>默认一定会执行一次</li><li>值发生变化会直接执行watch函数</li></ul><div class="language-js"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#676E95;font-style:italic;">/**</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;"> *</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;"> * </span><span style="color:#89DDFF;font-style:italic;">@</span><span style="color:#C792EA;font-style:italic;">param</span><span style="color:#676E95;font-style:italic;"> </span><span style="color:#A6ACCD;font-style:italic;">source</span><span style="color:#676E95;font-style:italic;"> 需要监听的数据(可能是函数，有可以是值)</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;"> * </span><span style="color:#89DDFF;font-style:italic;">@</span><span style="color:#C792EA;font-style:italic;">param</span><span style="color:#676E95;font-style:italic;"> </span><span style="color:#A6ACCD;font-style:italic;">cb</span><span style="color:#676E95;font-style:italic;"> 数据变化后的回调</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;"> * </span><span style="color:#89DDFF;font-style:italic;">@</span><span style="color:#C792EA;font-style:italic;">param</span><span style="color:#676E95;font-style:italic;"> </span><span style="color:#A6ACCD;font-style:italic;">options</span><span style="color:#676E95;font-style:italic;"> 配置项</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;"> * </span><span style="color:#89DDFF;font-style:italic;">@</span><span style="color:#C792EA;font-style:italic;">returns</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;"> */</span></span>
<span class="line"></span>
<span class="line"><span style="color:#676E95;font-style:italic;">// watch( () =&gt; count, ( newValue, oldValue ) =&gt; {</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;">// }, {</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;">//   deep: true,</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;">//   immediate: true</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;">// } );</span></span>
<span class="line"><span style="color:#C792EA;">function</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">watch</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;font-style:italic;">source</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#A6ACCD;font-style:italic;">cb</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#A6ACCD;font-style:italic;">options</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{})</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;font-style:italic;">return</span><span style="color:#F07178;"> </span><span style="color:#82AAFF;">doWatch</span><span style="color:#F07178;">(</span><span style="color:#A6ACCD;">source</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">cb</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">options</span><span style="color:#F07178;">)</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#676E95;font-style:italic;">// 默认会执行一次</span></span>
<span class="line"><span style="color:#C792EA;">function</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">watchEffect</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;font-style:italic;">source</span><span style="color:#89DDFF;">)</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;font-style:italic;">return</span><span style="color:#F07178;"> </span><span style="color:#82AAFF;">doWatch</span><span style="color:#F07178;">(</span><span style="color:#A6ACCD;">source</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">null,</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">{}</span><span style="color:#F07178;">)</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#C792EA;">function</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">doWatch</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;font-style:italic;">source</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#A6ACCD;font-style:italic;">cb</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#A6ACCD;font-style:italic;">options</span><span style="color:#89DDFF;">)</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#89DDFF;">  </span><span style="color:#676E95;font-style:italic;">// 如果不是函数包装成函数，方便后续处理</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#C792EA;">let</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">sourceHandler</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">source</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;font-style:italic;">if</span><span style="color:#F07178;"> (</span><span style="color:#89DDFF;">!</span><span style="color:#82AAFF;">isFunction</span><span style="color:#F07178;">(</span><span style="color:#A6ACCD;">source</span><span style="color:#F07178;">)) </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#82AAFF;">sourceHandler</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">()</span><span style="color:#F07178;"> </span><span style="color:#C792EA;">=&gt;</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">source</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#C792EA;">let</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">oldValue</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">&quot;&quot;</span><span style="color:#89DDFF;">;</span><span style="color:#F07178;"> </span><span style="color:#676E95;font-style:italic;">// 老值</span></span>
<span class="line"><span style="color:#89DDFF;">  </span><span style="color:#676E95;font-style:italic;">// 自定义effect执行器</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#C792EA;">let</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">schedular</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">()</span><span style="color:#F07178;"> </span><span style="color:#C792EA;">=&gt;</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#89DDFF;font-style:italic;">if</span><span style="color:#F07178;"> (</span><span style="color:#A6ACCD;">cb</span><span style="color:#F07178;">) </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#89DDFF;">      </span><span style="color:#676E95;font-style:italic;">// 或者最新的值</span></span>
<span class="line"><span style="color:#F07178;">      </span><span style="color:#C792EA;">let</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">newValue</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#82AAFF;">runner</span><span style="color:#F07178;">()</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#89DDFF;">      </span><span style="color:#676E95;font-style:italic;">// 如果新老值不一样，执行回调</span></span>
<span class="line"><span style="color:#F07178;">      </span><span style="color:#89DDFF;font-style:italic;">if</span><span style="color:#F07178;"> (</span><span style="color:#82AAFF;">hasChanged</span><span style="color:#F07178;">(</span><span style="color:#A6ACCD;">oldValue</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">newValue</span><span style="color:#F07178;">)) </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">        </span><span style="color:#82AAFF;">cb</span><span style="color:#F07178;">(</span><span style="color:#A6ACCD;">newValue</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">oldValue</span><span style="color:#F07178;">)</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#F07178;">        </span><span style="color:#A6ACCD;">oldValue</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">newValue</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#F07178;">      </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#89DDFF;">}</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;font-style:italic;">else</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#89DDFF;">      </span><span style="color:#676E95;font-style:italic;">// watchEffect没有回调，直接执行source</span></span>
<span class="line"><span style="color:#F07178;">      </span><span style="color:#82AAFF;">sourceHandler</span><span style="color:#F07178;">()</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;">};</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#C792EA;">let</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">runner</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#82AAFF;">effect</span><span style="color:#F07178;">(</span><span style="color:#A6ACCD;">sourceHandler</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">    lazy</span><span style="color:#89DDFF;">:</span><span style="color:#F07178;"> </span><span style="color:#FF9CAC;">true</span><span style="color:#89DDFF;">,</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#82AAFF;">schedular</span><span style="color:#89DDFF;">:</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">()</span><span style="color:#F07178;"> </span><span style="color:#C792EA;">=&gt;</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#89DDFF;">      </span><span style="color:#676E95;font-style:italic;">// 如果数据同一时间多次变更，会触发effect多次执行，我们只需要执行一次即可</span></span>
<span class="line"><span style="color:#F07178;">      </span><span style="color:#82AAFF;">queueJob</span><span style="color:#F07178;">(</span><span style="color:#A6ACCD;">schedular</span><span style="color:#F07178;">)</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#89DDFF;">},</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;">}</span><span style="color:#F07178;">)</span><span style="color:#89DDFF;">;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#89DDFF;">  </span><span style="color:#676E95;font-style:italic;">// 是否默认执行一次watch回调</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;font-style:italic;">if</span><span style="color:#F07178;"> (</span><span style="color:#A6ACCD;">options</span><span style="color:#89DDFF;">?.</span><span style="color:#A6ACCD;">immediate</span><span style="color:#F07178;">) </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#82AAFF;">schedular</span><span style="color:#F07178;">()</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#89DDFF;">  </span><span style="color:#676E95;font-style:italic;">// 或者监听的值，同时触发收集当前的effect，当监听的值发生变化时通知effect执行回调</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#A6ACCD;">oldValue</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#82AAFF;">runner</span><span style="color:#F07178;">()</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span></code></pre></div><h2 id="vue-computed-计算属性" tabindex="-1">Vue computed 计算属性 <a class="header-anchor" href="#vue-computed-计算属性" aria-label="Permalink to &quot;Vue computed 计算属性&quot;">​</a></h2><ul><li>计算属性是一个类，在初始化时，首先会初始化缓存的状态<code>dirty</code>,会创建一个 <code>lazy</code>的effect <code>不会立马执行</code>，并且把 getter 控制权交给 effect</li><li>当在取 <code>state.value</code> 时，触发 get 拦截，如果<code>没有缓存</code>会调用 effect 获取的计算属性的值，响应式数据会通过<code>track</code>收集当前的<code>计算属性effect</code>，同时会让计算实例收集<code>渲染的effect</code></li><li>当响应式数据发生变化时，触发set通知 effect 执行自定义的<code>schedular</code>，在<code>schedular中</code>取消缓存，通过执行<code>trigger</code>触发渲染的 effect更新视图</li></ul><div class="language-js"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#C792EA;">function</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">computed</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;"> </span><span style="color:#A6ACCD;font-style:italic;">handler</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">)</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#C792EA;">let</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">getter</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#C792EA;">let</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">setter</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;font-style:italic;">if</span><span style="color:#F07178;"> ( </span><span style="color:#89DDFF;">typeof</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">handler</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">===</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">&#39;</span><span style="color:#C3E88D;">function</span><span style="color:#89DDFF;">&#39;</span><span style="color:#F07178;"> ) </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#A6ACCD;">getter</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">handler</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#82AAFF;">setter</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">()</span><span style="color:#F07178;"> </span><span style="color:#C792EA;">=&gt;</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">      </span><span style="color:#A6ACCD;">console</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">warn</span><span style="color:#F07178;">( </span><span style="color:#89DDFF;">`</span><span style="color:#C3E88D;">computed not set</span><span style="color:#89DDFF;">`</span><span style="color:#F07178;"> )</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;">}</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;font-style:italic;">else</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;font-style:italic;">if</span><span style="color:#F07178;"> ( </span><span style="color:#82AAFF;">isObject</span><span style="color:#F07178;">( </span><span style="color:#A6ACCD;">handler</span><span style="color:#F07178;"> ) ) </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#A6ACCD;">getter</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">handler</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">set</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#A6ACCD;">setter</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">handler</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">get</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;">}</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;font-style:italic;">else</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#89DDFF;font-style:italic;">return</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">console</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">warn</span><span style="color:#F07178;">( </span><span style="color:#89DDFF;">`</span><span style="color:#C3E88D;">computed It must be a function or an object</span><span style="color:#89DDFF;">`</span><span style="color:#F07178;"> )</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;font-style:italic;">return</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">new</span><span style="color:#F07178;"> </span><span style="color:#82AAFF;">ComputedRefImpl</span><span style="color:#F07178;">( </span><span style="color:#A6ACCD;">getter</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">setter</span><span style="color:#F07178;"> )</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#C792EA;">class</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">ComputedRefImpl</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">  </span><span style="color:#C792EA;">public</span><span style="color:#A6ACCD;"> </span><span style="color:#F07178;">_value</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#A6ACCD;">  </span><span style="color:#C792EA;">public</span><span style="color:#A6ACCD;"> </span><span style="color:#F07178;">effect</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#A6ACCD;">  </span><span style="color:#C792EA;">public</span><span style="color:#A6ACCD;"> </span><span style="color:#F07178;">_dirty</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#FF9CAC;">true</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#A6ACCD;">  </span><span style="color:#C792EA;">constructor</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">public</span><span style="color:#A6ACCD;"> </span><span style="color:#A6ACCD;font-style:italic;">getter</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">public</span><span style="color:#A6ACCD;"> </span><span style="color:#A6ACCD;font-style:italic;">setter</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">)</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#89DDFF;">this.</span><span style="color:#A6ACCD;">effect</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#82AAFF;">effect</span><span style="color:#F07178;">( </span><span style="color:#A6ACCD;">getter</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">      lazy</span><span style="color:#89DDFF;">:</span><span style="color:#F07178;"> </span><span style="color:#FF9CAC;">true</span><span style="color:#89DDFF;">,</span><span style="color:#676E95;font-style:italic;">// 在取值的时候，才执行getter</span></span>
<span class="line"><span style="color:#F07178;">      </span><span style="color:#82AAFF;">schedular</span><span style="color:#89DDFF;">:</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">()</span><span style="color:#F07178;"> </span><span style="color:#C792EA;">=&gt;</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#89DDFF;">        </span><span style="color:#676E95;font-style:italic;">// 1、计算属性响应式数据发生改变后，取消缓存</span></span>
<span class="line"><span style="color:#F07178;">        </span><span style="color:#89DDFF;">this.</span><span style="color:#A6ACCD;">_dirty</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#FF9CAC;">true</span></span>
<span class="line"><span style="color:#89DDFF;">        </span><span style="color:#676E95;font-style:italic;">// 2、通知渲染的effect更新视图</span></span>
<span class="line"><span style="color:#F07178;">        </span><span style="color:#82AAFF;">trigger</span><span style="color:#F07178;">( </span><span style="color:#89DDFF;">this,</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">TriggerOrTypes</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">UPDATE</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">value</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">this.</span><span style="color:#A6ACCD;">_value</span><span style="color:#F07178;"> )</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#F07178;">      </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#89DDFF;">}</span><span style="color:#F07178;"> )</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#A6ACCD;">  </span><span style="color:#C792EA;">get</span><span style="color:#A6ACCD;"> </span><span style="color:#F07178;">value</span><span style="color:#89DDFF;">()</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#89DDFF;">    </span><span style="color:#676E95;font-style:italic;">// 是否被缓存</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#89DDFF;font-style:italic;">if</span><span style="color:#F07178;"> ( </span><span style="color:#89DDFF;">this.</span><span style="color:#A6ACCD;">_dirty</span><span style="color:#F07178;"> ) </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#89DDFF;">      </span><span style="color:#676E95;font-style:italic;">// 用户在取值的时候，会通过effect调用计算属性的getter方法，让响应式数据去收集计算属性effect</span></span>
<span class="line"><span style="color:#F07178;">      </span><span style="color:#89DDFF;">this.</span><span style="color:#A6ACCD;">_value</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">this.</span><span style="color:#82AAFF;">effect</span><span style="color:#F07178;">()</span></span>
<span class="line"><span style="color:#89DDFF;">      </span><span style="color:#676E95;font-style:italic;">// 缓存值</span></span>
<span class="line"><span style="color:#F07178;">      </span><span style="color:#89DDFF;">this.</span><span style="color:#A6ACCD;">_dirty</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#FF9CAC;">false</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#89DDFF;">    </span><span style="color:#676E95;font-style:italic;">// 计算属性收集渲染的effect</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#82AAFF;">track</span><span style="color:#F07178;">( </span><span style="color:#89DDFF;">this,</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">TrackOpTypes</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">GET</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">value</span><span style="color:#89DDFF;">&quot;</span><span style="color:#F07178;"> )</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#89DDFF;font-style:italic;">return</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">this.</span><span style="color:#A6ACCD;">_value</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#A6ACCD;">  </span><span style="color:#C792EA;">set</span><span style="color:#A6ACCD;"> </span><span style="color:#F07178;">value</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;"> </span><span style="color:#A6ACCD;font-style:italic;">newValue</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">)</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#89DDFF;">this.</span><span style="color:#82AAFF;">setter</span><span style="color:#F07178;">( </span><span style="color:#A6ACCD;">newValue</span><span style="color:#F07178;"> )</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span></code></pre></div><h2 id="vue-props-处理" tabindex="-1">Vue Props 处理 <a class="header-anchor" href="#vue-props-处理" aria-label="Permalink to &quot;Vue Props 处理&quot;">​</a></h2><ul><li>子组件在创建createVNode时，如果父组件有传递数据，会将数据存储在Vnode props对象中</li><li>子组件在创建组件实例对象时，会把自己接受的props数据，存储在 实例propsOptionse对象中</li><li>子组件在渲染的时候，会调用 <code>initProps</code>，如果父组件传递的数据在<code>子组件中有定义</code>存储在<code>组件实例props中</code></li><li>如果是未接收的属性，将全部存储在组件实例<code>attrs</code>上</li></ul><div class="language-js"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#C792EA;">const</span><span style="color:#A6ACCD;"> VueComponent </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">  </span><span style="color:#F07178;">props</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#F07178;">name</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> String</span><span style="color:#89DDFF;">,</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#F07178;">age</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> Number</span><span style="color:#89DDFF;">,</span></span>
<span class="line"><span style="color:#A6ACCD;">  </span><span style="color:#89DDFF;">},</span></span>
<span class="line"><span style="color:#89DDFF;">  </span><span style="color:#676E95;font-style:italic;">// ...</span></span>
<span class="line"><span style="color:#89DDFF;">};</span></span>
<span class="line"></span>
<span class="line"><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> app </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">createApp</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">  </span><span style="color:#82AAFF;">render</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">()</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">=&gt;</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#89DDFF;font-style:italic;">return</span><span style="color:#F07178;"> </span><span style="color:#82AAFF;">h</span><span style="color:#F07178;">(</span><span style="color:#A6ACCD;">VueComponent</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">      name</span><span style="color:#89DDFF;">:</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">hulei</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">,</span></span>
<span class="line"><span style="color:#F07178;">      age</span><span style="color:#89DDFF;">:</span><span style="color:#F07178;"> </span><span style="color:#F78C6C;">18</span><span style="color:#89DDFF;">,</span></span>
<span class="line"><span style="color:#F07178;">      add</span><span style="color:#89DDFF;">:</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">上海</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">,</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#89DDFF;">}</span><span style="color:#F07178;">)</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;">},</span></span>
<span class="line"><span style="color:#89DDFF;">}</span><span style="color:#A6ACCD;">)</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#A6ACCD;">app</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">mount</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">#app</span><span style="color:#89DDFF;">&quot;</span><span style="color:#A6ACCD;">)</span><span style="color:#89DDFF;">;</span></span>
<span class="line"></span>
<span class="line"></span>
<span class="line"><span style="color:#676E95;font-style:italic;">// h=&gt; createVNode( type, propsOrChildren, children );</span></span>
<span class="line"><span style="color:#C792EA;">function</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">createVNode</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;"> </span><span style="color:#A6ACCD;font-style:italic;">type</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#A6ACCD;font-style:italic;">props</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#A6ACCD;font-style:italic;">children</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">null</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">)</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#C792EA;">const</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">vnode</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">    __v_isVnode</span><span style="color:#89DDFF;">:</span><span style="color:#F07178;"> </span><span style="color:#FF9CAC;">true</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> </span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#A6ACCD;">type</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> </span><span style="color:#676E95;font-style:italic;">// 此时是一个(VueComponent)组件</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#A6ACCD;">props</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> </span><span style="color:#676E95;font-style:italic;">// 子组件在创建createVNode时，如果父组件有传递数据，会将数据存储在Vnode props对象中</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#A6ACCD;">children</span><span style="color:#89DDFF;">,</span></span>
<span class="line"><span style="color:#F07178;">    component</span><span style="color:#89DDFF;">:</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">null,</span><span style="color:#F07178;"> </span></span>
<span class="line"><span style="color:#F07178;">    el</span><span style="color:#89DDFF;">:</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">null,</span></span>
<span class="line"><span style="color:#F07178;">    key</span><span style="color:#89DDFF;">:</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">props</span><span style="color:#89DDFF;">?.</span><span style="color:#A6ACCD;">key</span><span style="color:#89DDFF;">,</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#A6ACCD;">shapeFlag</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> </span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;">};</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#82AAFF;">normalizeChildren</span><span style="color:#F07178;">( </span><span style="color:#A6ACCD;">vnode</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">children</span><span style="color:#F07178;"> )</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;font-style:italic;">return</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">vnode</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#89DDFF;">};</span></span>
<span class="line"></span>
<span class="line"><span style="color:#C792EA;">const</span><span style="color:#A6ACCD;"> instance </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">  </span><span style="color:#F07178;">uuid</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> uuid</span><span style="color:#89DDFF;">++,</span></span>
<span class="line"><span style="color:#A6ACCD;">  </span><span style="color:#F07178;">__v_isVNode</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#FF9CAC;">true</span><span style="color:#89DDFF;">,</span></span>
<span class="line"><span style="color:#A6ACCD;">  vnode</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#676E95;font-style:italic;">// 组件对应的虚拟节点</span></span>
<span class="line"><span style="color:#A6ACCD;">  </span><span style="color:#F07178;">subTree</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">null,</span><span style="color:#A6ACCD;"> </span></span>
<span class="line"><span style="color:#A6ACCD;">  type</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#676E95;font-style:italic;">// 组件对象</span></span>
<span class="line"><span style="color:#A6ACCD;">  </span><span style="color:#F07178;">propsOptions</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> vnode</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">type</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">props </span><span style="color:#89DDFF;">||</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{},</span><span style="color:#A6ACCD;"> </span><span style="color:#676E95;font-style:italic;">// 子组件在创建组件实例对象时，会把自己接受的props数据，存储在 实例propsOptionse对象中</span></span>
<span class="line"><span style="color:#A6ACCD;">  </span><span style="color:#F07178;">ctx</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{}</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;font-style:italic;">as</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">any</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span></span>
<span class="line"><span style="color:#A6ACCD;">  </span><span style="color:#F07178;">props</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{},</span><span style="color:#A6ACCD;"> </span><span style="color:#676E95;font-style:italic;">// 组件的属性</span></span>
<span class="line"><span style="color:#A6ACCD;">  </span><span style="color:#F07178;">attrs</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{},</span><span style="color:#A6ACCD;"> </span></span>
<span class="line"><span style="color:#A6ACCD;">  </span><span style="color:#F07178;">slots</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{},</span><span style="color:#A6ACCD;"> </span></span>
<span class="line"><span style="color:#A6ACCD;">  </span><span style="color:#F07178;">setupState</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{},</span><span style="color:#A6ACCD;"> </span></span>
<span class="line"><span style="color:#A6ACCD;">  </span><span style="color:#F07178;">isMounted</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#FF9CAC;">false</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span></span>
<span class="line"><span style="color:#A6ACCD;">  </span><span style="color:#F07178;">exposed</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{},</span><span style="color:#A6ACCD;"> </span></span>
<span class="line"><span style="color:#A6ACCD;">  parent</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span></span>
<span class="line"><span style="color:#A6ACCD;">  </span><span style="color:#F07178;">provides</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;">parent </span><span style="color:#89DDFF;">?</span><span style="color:#A6ACCD;"> parent</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">provides </span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> Object</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">create</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">null</span><span style="color:#A6ACCD;">) </span></span>
<span class="line"><span style="color:#89DDFF;">};</span></span></code></pre></div><div class="language-js"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#676E95;font-style:italic;">// 解析vnode将数据挂载到组件实例上</span></span>
<span class="line"><span style="color:#C792EA;">function</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">setupComponent</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;"> </span><span style="color:#A6ACCD;font-style:italic;">instance</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">)</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#C792EA;">let</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">{</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">props</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">children</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">}</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">instance</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">vnode</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#89DDFF;">  </span><span style="color:#676E95;font-style:italic;">// 如果子组件有接收props，将会实例在props上，否则全部在实例attrs上</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#82AAFF;">initProps</span><span style="color:#F07178;">(</span><span style="color:#A6ACCD;">instance</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;">props</span><span style="color:#F07178;">)</span></span>
<span class="line"></span>
<span class="line"><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#C792EA;">const</span><span style="color:#A6ACCD;"> initProps </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;font-style:italic;">instance</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#A6ACCD;font-style:italic;">userProps</span><span style="color:#89DDFF;">)</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">=&gt;</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#C792EA;">const</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">attrs</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">{};</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#C792EA;">const</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">props</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">{};</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#C792EA;">const</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">options</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">instance</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">propsOptions</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">||</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">{};</span><span style="color:#F07178;"> </span><span style="color:#676E95;font-style:italic;">// 子组件上接受的props</span></span>
<span class="line"><span style="color:#89DDFF;">  </span><span style="color:#676E95;font-style:italic;">// 父组件传递的props</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;font-style:italic;">if</span><span style="color:#F07178;"> (</span><span style="color:#A6ACCD;">userProps</span><span style="color:#F07178;">) </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#89DDFF;font-style:italic;">for</span><span style="color:#F07178;"> (</span><span style="color:#C792EA;">let</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">key</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">in</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">userProps</span><span style="color:#F07178;">) </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">      </span><span style="color:#C792EA;">const</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">value</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">userProps</span><span style="color:#F07178;">[</span><span style="color:#A6ACCD;">key</span><span style="color:#F07178;">]</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#89DDFF;">      </span><span style="color:#676E95;font-style:italic;">// 如果子组件有接受作为props，否则作为attrs</span></span>
<span class="line"><span style="color:#F07178;">      </span><span style="color:#89DDFF;font-style:italic;">if</span><span style="color:#F07178;"> (</span><span style="color:#A6ACCD;">key</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">in</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">options</span><span style="color:#F07178;">) </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">        </span><span style="color:#A6ACCD;">props</span><span style="color:#F07178;">[</span><span style="color:#A6ACCD;">key</span><span style="color:#F07178;">] </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">value</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#F07178;">      </span><span style="color:#89DDFF;">}</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;font-style:italic;">else</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">        </span><span style="color:#A6ACCD;">attrs</span><span style="color:#F07178;">[</span><span style="color:#A6ACCD;">key</span><span style="color:#F07178;">] </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">value</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#F07178;">      </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#A6ACCD;">instance</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">attrs</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">attrs</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#A6ACCD;">instance</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">props</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#82AAFF;">reactive</span><span style="color:#F07178;">(</span><span style="color:#A6ACCD;">props</span><span style="color:#F07178;">)</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#89DDFF;">};</span></span></code></pre></div><h2 id="emits-原理" tabindex="-1">emits 原理 <a class="header-anchor" href="#emits-原理" aria-label="Permalink to &quot;emits 原理&quot;">​</a></h2><div class="tip custom-block"><p class="custom-block-title">TIP</p><p>emits 作用主要是让子组件能够调用父组件的函数</p></div><ul><li>1、子组件在初始化时，非 props 的接收的属性，将全部存储在子组件实例<code>attrs</code>上</li><li>2、当触子组件在触发 emit 函数时，通过函数名称子组件实例<code>attrs</code>上去查找，如果有就执行父组件的函数(其实就是发布/订阅)</li></ul><div class="language-js"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#676E95;font-style:italic;">// 构建setup 下上文content</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;">// setup(props, content) {</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;">//    const { attrs, slots, emit, expose } = content</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;">//  }</span></span>
<span class="line"><span style="color:#C792EA;">function</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">createSetupContext</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;font-style:italic;">instance</span><span style="color:#89DDFF;">)</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;font-style:italic;">return</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">    attrs</span><span style="color:#89DDFF;">:</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">instance</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">attrs</span><span style="color:#89DDFF;">,</span></span>
<span class="line"><span style="color:#F07178;">    slots</span><span style="color:#89DDFF;">:</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">instance</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">slots</span><span style="color:#89DDFF;">,</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#82AAFF;">emit</span><span style="color:#89DDFF;">:</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;font-style:italic;">eventName</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">...</span><span style="color:#A6ACCD;font-style:italic;">args</span><span style="color:#89DDFF;">)</span><span style="color:#F07178;"> </span><span style="color:#C792EA;">=&gt;</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">      </span><span style="color:#C792EA;">let</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">bindName</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">`</span><span style="color:#C3E88D;">on</span><span style="color:#89DDFF;">${</span><span style="color:#A6ACCD;">eventName[</span><span style="color:#F78C6C;">0</span><span style="color:#A6ACCD;">]</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">toUpperCase</span><span style="color:#A6ACCD;">()</span><span style="color:#89DDFF;">}${</span><span style="color:#A6ACCD;">eventName</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">slice</span><span style="color:#A6ACCD;">(</span><span style="color:#F78C6C;">1</span><span style="color:#A6ACCD;">)</span><span style="color:#89DDFF;">}`</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#F07178;">      </span><span style="color:#C792EA;">const</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">handler</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">instance</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">attrs</span><span style="color:#F07178;">[</span><span style="color:#A6ACCD;">bindName</span><span style="color:#F07178;">]</span><span style="color:#89DDFF;">;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F07178;">      </span><span style="color:#89DDFF;font-style:italic;">if</span><span style="color:#F07178;"> (</span><span style="color:#A6ACCD;">handler</span><span style="color:#F07178;">) </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">        </span><span style="color:#C792EA;">let</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">handlers</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">Array</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">isArray</span><span style="color:#F07178;">(</span><span style="color:#A6ACCD;">handler</span><span style="color:#F07178;">) </span><span style="color:#89DDFF;">?</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">handler</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">:</span><span style="color:#F07178;"> [</span><span style="color:#A6ACCD;">handler</span><span style="color:#F07178;">]</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#F07178;">        </span><span style="color:#A6ACCD;">handlers</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">forEach</span><span style="color:#F07178;">(</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;font-style:italic;">handler</span><span style="color:#89DDFF;">)</span><span style="color:#F07178;"> </span><span style="color:#C792EA;">=&gt;</span><span style="color:#F07178;"> </span><span style="color:#82AAFF;">handler</span><span style="color:#F07178;">(</span><span style="color:#89DDFF;">...</span><span style="color:#A6ACCD;">args</span><span style="color:#F07178;">))</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#F07178;">      </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#89DDFF;">},</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#82AAFF;">expose</span><span style="color:#89DDFF;">:</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">()</span><span style="color:#F07178;"> </span><span style="color:#C792EA;">=&gt;</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">{},</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;">};</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span></code></pre></div><h2 id="expose-实例原理" tabindex="-1">expose 实例原理 <a class="header-anchor" href="#expose-实例原理" aria-label="Permalink to &quot;expose 实例原理&quot;">​</a></h2><div class="tip custom-block"><p class="custom-block-title">TIP</p><p>将子组件属性或者函数暴露出去，让父组件可以通过 ref 去调用</p></div><ul><li>1、当子组件在调用 expose 时，其实就是把需要提供出去的属性，存储在<code>自己实例 exposed 属性上</code></li><li>2、父组件可以<code>通过 ref </code>获取到<code>子组件的实例</code>，从而可以调用子组件暴露的函数和属性</li></ul><div class="language-js"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#82AAFF;">setup</span><span style="color:#A6ACCD;">(props</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span><span style="color:#A6ACCD;"> attrs</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> slots</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> emit</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;">expose </span><span style="color:#89DDFF;">}</span><span style="color:#A6ACCD;">) </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#C792EA;">const</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">sava</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">()</span><span style="color:#C792EA;">=&gt;</span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">          </span><span style="color:#82AAFF;">alert</span><span style="color:#F07178;">(</span><span style="color:#89DDFF;">&#39;</span><span style="color:#C3E88D;">expose</span><span style="color:#89DDFF;">&#39;</span><span style="color:#F07178;">)</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#89DDFF;">  </span><span style="color:#676E95;font-style:italic;">// 暴露自己的函数</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#82AAFF;">expose</span><span style="color:#F07178;">(</span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">      </span><span style="color:#A6ACCD;">sava</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#89DDFF;">}</span><span style="color:#F07178;">)</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span>
<span class="line"></span>
<span class="line"></span>
<span class="line"><span style="color:#676E95;font-style:italic;">// 构建setup 下上文content</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;">// setup(props, content) {</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;">//    const { attrs, slots, emit, expose } = content</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;">//  }</span></span>
<span class="line"><span style="color:#C792EA;">function</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">createSetupContext</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;font-style:italic;">instance</span><span style="color:#89DDFF;">)</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;font-style:italic;">return</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">    attrs</span><span style="color:#89DDFF;">:</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">instance</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">attrs</span><span style="color:#89DDFF;">,</span></span>
<span class="line"><span style="color:#F07178;">    slots</span><span style="color:#89DDFF;">:</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">instance</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">slots</span><span style="color:#89DDFF;">,</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#82AAFF;">emit</span><span style="color:#89DDFF;">:</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;font-style:italic;">eventName</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">...</span><span style="color:#A6ACCD;font-style:italic;">args</span><span style="color:#89DDFF;">)</span><span style="color:#F07178;"> </span><span style="color:#C792EA;">=&gt;</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">      </span><span style="color:#C792EA;">let</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">bindName</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">`</span><span style="color:#C3E88D;">on</span><span style="color:#89DDFF;">${</span><span style="color:#A6ACCD;">eventName[</span><span style="color:#F78C6C;">0</span><span style="color:#A6ACCD;">]</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">toUpperCase</span><span style="color:#A6ACCD;">()</span><span style="color:#89DDFF;">}${</span><span style="color:#A6ACCD;">eventName</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">slice</span><span style="color:#A6ACCD;">(</span><span style="color:#F78C6C;">1</span><span style="color:#A6ACCD;">)</span><span style="color:#89DDFF;">}`</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#F07178;">      </span><span style="color:#C792EA;">const</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">handler</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">instance</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">attrs</span><span style="color:#F07178;">[</span><span style="color:#A6ACCD;">bindName</span><span style="color:#F07178;">]</span><span style="color:#89DDFF;">;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F07178;">      </span><span style="color:#89DDFF;font-style:italic;">if</span><span style="color:#F07178;"> (</span><span style="color:#A6ACCD;">handler</span><span style="color:#F07178;">) </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">        </span><span style="color:#C792EA;">let</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">handlers</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">Array</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">isArray</span><span style="color:#F07178;">(</span><span style="color:#A6ACCD;">handler</span><span style="color:#F07178;">) </span><span style="color:#89DDFF;">?</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">handler</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">:</span><span style="color:#F07178;"> [</span><span style="color:#A6ACCD;">handler</span><span style="color:#F07178;">]</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#F07178;">        </span><span style="color:#A6ACCD;">handlers</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">forEach</span><span style="color:#F07178;">(</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;font-style:italic;">handler</span><span style="color:#89DDFF;">)</span><span style="color:#F07178;"> </span><span style="color:#C792EA;">=&gt;</span><span style="color:#F07178;"> </span><span style="color:#82AAFF;">handler</span><span style="color:#F07178;">(</span><span style="color:#89DDFF;">...</span><span style="color:#A6ACCD;">args</span><span style="color:#F07178;">))</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#F07178;">      </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#89DDFF;">},</span></span>
<span class="line"><span style="color:#F07178;">    expose</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;font-style:italic;">exposed</span><span style="color:#89DDFF;">)</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#89DDFF;">      </span><span style="color:#676E95;font-style:italic;">// 主要用于ref ，通过ref获取组件的时候 在vue里只能获取到组件实例，但是在vue3中如果提供了</span></span>
<span class="line"><span style="color:#89DDFF;">      </span><span style="color:#676E95;font-style:italic;">// exposed 则获取的就是exposed属性</span></span>
<span class="line"><span style="color:#F07178;">      </span><span style="color:#A6ACCD;">instance</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">exposed</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">exposed</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#89DDFF;">},</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;">};</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span></code></pre></div><h2 id="slot-插槽-原理" tabindex="-1">slot 插槽 原理 <a class="header-anchor" href="#slot-插槽-原理" aria-label="Permalink to &quot;slot 插槽 原理&quot;">​</a></h2><ul><li>1、模版在编译的时候，会把 slot 插槽转换成一个对象</li><li>2、如果是匿名插槽会 <code>default 会作为对象的 属性</code>，如果是<code>具明插槽 </code>插槽的名字作为属性</li><li>3、在构建<code>虚拟节点</code>的时候，如果子节点是一个对象，会把子节点标记成插槽</li><li>4、在创建组件实例的时候，如果 Vnode 上有<code>children子节点</code>会执行<code>initSlots(instance,children)</code></li><li>5、如果 children 是插槽类型，会把 children 对象，存储在组件实例的 slots 上，并且 slots 会传递到上下文对象中</li><li>6、让组件在渲染的时间，可以直接调用上下文中的 slots 进行渲染</li></ul><div class="language-js"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span><span style="color:#A6ACCD;"> reactive</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> createApp</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> h </span><span style="color:#89DDFF;">}</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> VueRuntimeDOM</span><span style="color:#89DDFF;">;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#C792EA;">const</span><span style="color:#A6ACCD;"> VueComponent </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">  </span><span style="color:#F07178;">setup</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;font-style:italic;">props</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span><span style="color:#A6ACCD;"> </span><span style="color:#A6ACCD;font-style:italic;">slots</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">})</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#89DDFF;font-style:italic;">return</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">()</span><span style="color:#F07178;"> </span><span style="color:#C792EA;">=&gt;</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">      </span><span style="color:#89DDFF;font-style:italic;">return</span><span style="color:#F07178;"> </span><span style="color:#82AAFF;">h</span><span style="color:#F07178;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">div</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> [</span></span>
<span class="line"><span style="color:#F07178;">        </span><span style="color:#82AAFF;">h</span><span style="color:#F07178;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">div</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">slots</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">default</span><span style="color:#F07178;">())</span><span style="color:#89DDFF;">,</span></span>
<span class="line"><span style="color:#F07178;">        </span><span style="color:#82AAFF;">h</span><span style="color:#F07178;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">div</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">slots</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">header</span><span style="color:#F07178;">())</span><span style="color:#89DDFF;">,</span></span>
<span class="line"><span style="color:#F07178;">        </span><span style="color:#82AAFF;">h</span><span style="color:#F07178;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">div</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">slots</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">main</span><span style="color:#F07178;">())</span><span style="color:#89DDFF;">,</span></span>
<span class="line"><span style="color:#F07178;">        </span><span style="color:#82AAFF;">h</span><span style="color:#F07178;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">div</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">slots</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">footer</span><span style="color:#F07178;">())</span><span style="color:#89DDFF;">,</span></span>
<span class="line"><span style="color:#F07178;">      ])</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#89DDFF;">};</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;">},</span></span>
<span class="line"><span style="color:#89DDFF;">};</span></span>
<span class="line"></span>
<span class="line"><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> app </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">createApp</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">  </span><span style="color:#82AAFF;">render</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">()</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">=&gt;</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#89DDFF;font-style:italic;">return</span><span style="color:#F07178;"> </span><span style="color:#82AAFF;">h</span><span style="color:#F07178;">(</span><span style="color:#A6ACCD;">VueComponent</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">null,</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">      </span><span style="color:#82AAFF;">default</span><span style="color:#89DDFF;">:</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">()</span><span style="color:#F07178;"> </span><span style="color:#C792EA;">=&gt;</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">        </span><span style="color:#89DDFF;font-style:italic;">return</span><span style="color:#F07178;"> </span><span style="color:#82AAFF;">h</span><span style="color:#F07178;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">a</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">default</span><span style="color:#89DDFF;">&quot;</span><span style="color:#F07178;">)</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#F07178;">      </span><span style="color:#89DDFF;">},</span></span>
<span class="line"><span style="color:#F07178;">      </span><span style="color:#82AAFF;">header</span><span style="color:#89DDFF;">:</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">()</span><span style="color:#F07178;"> </span><span style="color:#C792EA;">=&gt;</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">        </span><span style="color:#89DDFF;font-style:italic;">return</span><span style="color:#F07178;"> </span><span style="color:#82AAFF;">h</span><span style="color:#F07178;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">a</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">hello</span><span style="color:#89DDFF;">&quot;</span><span style="color:#F07178;">)</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#F07178;">      </span><span style="color:#89DDFF;">},</span></span>
<span class="line"><span style="color:#F07178;">      </span><span style="color:#82AAFF;">main</span><span style="color:#89DDFF;">:</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">()</span><span style="color:#F07178;"> </span><span style="color:#C792EA;">=&gt;</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">        </span><span style="color:#89DDFF;font-style:italic;">return</span><span style="color:#F07178;"> </span><span style="color:#82AAFF;">h</span><span style="color:#F07178;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">a</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">vue</span><span style="color:#89DDFF;">&quot;</span><span style="color:#F07178;">)</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#F07178;">      </span><span style="color:#89DDFF;">},</span></span>
<span class="line"><span style="color:#F07178;">      </span><span style="color:#82AAFF;">footer</span><span style="color:#89DDFF;">:</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">()</span><span style="color:#F07178;"> </span><span style="color:#C792EA;">=&gt;</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">        </span><span style="color:#89DDFF;font-style:italic;">return</span><span style="color:#F07178;"> </span><span style="color:#82AAFF;">h</span><span style="color:#F07178;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">a</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">hulei</span><span style="color:#89DDFF;">&quot;</span><span style="color:#F07178;">)</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#F07178;">      </span><span style="color:#89DDFF;">},</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#89DDFF;">}</span><span style="color:#F07178;">)</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;">},</span></span>
<span class="line"><span style="color:#89DDFF;">}</span><span style="color:#A6ACCD;">)</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#A6ACCD;">app</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">mount</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">#app</span><span style="color:#89DDFF;">&quot;</span><span style="color:#A6ACCD;">)</span><span style="color:#89DDFF;">;</span></span></code></pre></div><div class="language-js"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#676E95;font-style:italic;">// 虚拟节点的子节点处理</span></span>
<span class="line"><span style="color:#C792EA;">function</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">normalizeChildren</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;font-style:italic;">vnode</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#A6ACCD;font-style:italic;">children</span><span style="color:#89DDFF;">)</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#C792EA;">let</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">type</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#F78C6C;">0</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;font-style:italic;">if</span><span style="color:#F07178;"> (</span><span style="color:#A6ACCD;">children</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">==</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">null</span><span style="color:#F07178;">) </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;">}</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;font-style:italic;">else</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;font-style:italic;">if</span><span style="color:#F07178;"> (</span><span style="color:#82AAFF;">isArray</span><span style="color:#F07178;">(</span><span style="color:#A6ACCD;">children</span><span style="color:#F07178;">)) </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#A6ACCD;">type</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">ShapeFlags</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">ARRAY_CHILDREN</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;">}</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;font-style:italic;">else</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;font-style:italic;">if</span><span style="color:#F07178;"> (</span><span style="color:#82AAFF;">isObject</span><span style="color:#F07178;">(</span><span style="color:#A6ACCD;">children</span><span style="color:#F07178;">)) </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#89DDFF;">    </span><span style="color:#676E95;font-style:italic;">// 子节点是啥槽</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#A6ACCD;">type</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">ShapeFlags</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">SLOTS_CHILDREN</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;">}</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;font-style:italic;">else</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#A6ACCD;">type</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">ShapeFlags</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">TEXT_CHILDREN</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#A6ACCD;">vnode</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">shapeFlag</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">vnode</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">shapeFlag</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">|</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">type</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span></code></pre></div><div class="language-js"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#676E95;font-style:italic;">// 如果有插槽，将插槽存储在组件实例slots上</span></span>
<span class="line"><span style="color:#C792EA;">const</span><span style="color:#A6ACCD;"> initSlots </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;font-style:italic;">instance</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#A6ACCD;font-style:italic;">children</span><span style="color:#89DDFF;">)</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">=&gt;</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;font-style:italic;">if</span><span style="color:#F07178;"> (</span><span style="color:#A6ACCD;">instance</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">vnode</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">shapeFlag</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">&amp;</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">ShapeFlags</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">SLOTS_CHILDREN</span><span style="color:#F07178;">) </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#89DDFF;">    </span><span style="color:#676E95;font-style:italic;">// 包含插槽 则说明children 是插槽</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#A6ACCD;">instance</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">slots</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">children</span><span style="color:#89DDFF;">;</span><span style="color:#F07178;"> </span><span style="color:#676E95;font-style:italic;">// 将用户的children 映射到实例上</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#89DDFF;">};</span></span>
<span class="line"></span>
<span class="line"><span style="color:#676E95;font-style:italic;">// 解析vnode将数据挂载到组件实例上</span></span>
<span class="line"><span style="color:#C792EA;">function</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">setupComponent</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;font-style:italic;">instance</span><span style="color:#89DDFF;">)</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#C792EA;">let</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">{</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">props</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">children</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">}</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">instance</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">vnode</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#82AAFF;">initSlots</span><span style="color:#F07178;">(</span><span style="color:#A6ACCD;">instance</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">children</span><span style="color:#F07178;">)</span><span style="color:#89DDFF;">;</span><span style="color:#F07178;"> </span><span style="color:#676E95;font-style:italic;">// 插槽的解析</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span></code></pre></div><div class="language-js"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#676E95;font-style:italic;">// 构建setup 下上文content</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;">// setup(props, content) {</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;">//    const { attrs, slots, emit, expose } = content</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;">//  }</span></span>
<span class="line"><span style="color:#C792EA;">function</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">createSetupContext</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;font-style:italic;">instance</span><span style="color:#89DDFF;">)</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;font-style:italic;">return</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">    attrs</span><span style="color:#89DDFF;">:</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">instance</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">attrs</span><span style="color:#89DDFF;">,</span></span>
<span class="line"><span style="color:#F07178;">    slots</span><span style="color:#89DDFF;">:</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">instance</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">slots</span><span style="color:#89DDFF;">,</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#82AAFF;">emit</span><span style="color:#89DDFF;">:</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;font-style:italic;">eventName</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">...</span><span style="color:#A6ACCD;font-style:italic;">args</span><span style="color:#89DDFF;">)</span><span style="color:#F07178;"> </span><span style="color:#C792EA;">=&gt;</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">      </span><span style="color:#C792EA;">let</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">bindName</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">`</span><span style="color:#C3E88D;">on</span><span style="color:#89DDFF;">${</span><span style="color:#A6ACCD;">eventName[</span><span style="color:#F78C6C;">0</span><span style="color:#A6ACCD;">]</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">toUpperCase</span><span style="color:#A6ACCD;">()</span><span style="color:#89DDFF;">}${</span><span style="color:#A6ACCD;">eventName</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">slice</span><span style="color:#A6ACCD;">(</span><span style="color:#F78C6C;">1</span><span style="color:#A6ACCD;">)</span><span style="color:#89DDFF;">}`</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#F07178;">      </span><span style="color:#C792EA;">const</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">handler</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">instance</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">attrs</span><span style="color:#F07178;">[</span><span style="color:#A6ACCD;">bindName</span><span style="color:#F07178;">]</span><span style="color:#89DDFF;">;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F07178;">      </span><span style="color:#89DDFF;font-style:italic;">if</span><span style="color:#F07178;"> (</span><span style="color:#A6ACCD;">handler</span><span style="color:#F07178;">) </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">        </span><span style="color:#C792EA;">let</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">handlers</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">Array</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">isArray</span><span style="color:#F07178;">(</span><span style="color:#A6ACCD;">handler</span><span style="color:#F07178;">) </span><span style="color:#89DDFF;">?</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">handler</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">:</span><span style="color:#F07178;"> [</span><span style="color:#A6ACCD;">handler</span><span style="color:#F07178;">]</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#F07178;">        </span><span style="color:#A6ACCD;">handlers</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">forEach</span><span style="color:#F07178;">(</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;font-style:italic;">handler</span><span style="color:#89DDFF;">)</span><span style="color:#F07178;"> </span><span style="color:#C792EA;">=&gt;</span><span style="color:#F07178;"> </span><span style="color:#82AAFF;">handler</span><span style="color:#F07178;">(</span><span style="color:#89DDFF;">...</span><span style="color:#A6ACCD;">args</span><span style="color:#F07178;">))</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#F07178;">      </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#89DDFF;">},</span></span>
<span class="line"><span style="color:#F07178;">    expose</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;font-style:italic;">exposed</span><span style="color:#89DDFF;">)</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#89DDFF;">      </span><span style="color:#676E95;font-style:italic;">// 主要用于ref ，通过ref获取组件的时候 在vue里只能获取到组件实例，但是在vue3中如果提供了</span></span>
<span class="line"><span style="color:#89DDFF;">      </span><span style="color:#676E95;font-style:italic;">// exposed 则获取的就是exposed属性</span></span>
<span class="line"><span style="color:#F07178;">      </span><span style="color:#A6ACCD;">instance</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">exposed</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">exposed</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#89DDFF;">},</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;">};</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span></code></pre></div><h2 id="provide-or-inject" tabindex="-1">provide or inject <a class="header-anchor" href="#provide-or-inject" aria-label="Permalink to &quot;provide or inject&quot;">​</a></h2><div class="tip custom-block"><p class="custom-block-title">TIP</p><p>provide or inject 必须在组件中使用</p><p>provide 和 inject 类似于<code>内容提供者和消费者</code>，<code>任何</code>下级的组件都可以<code>消费</code>父组件的提供的 provide</p></div><ul><li>1、当一个组件在创建组件实例时，会存储自己的父组件是谁，如果父组件有 provides，就会将父组件的 provides 存储在当前组件实例 provides 上，最终会形成类似一个原型链</li><li>2、provide:当组件中调用 provide 时，会去父组件实例上查找 provides，如果有会进行合并，存储在当前组件实例的 provides 上</li><li>3、inject:当组件中调用 inject 时，会去父组件实例上查找 provides，如果有返回父组件提供的，如果没有返回默认值</li></ul><div class="language-js"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#676E95;font-style:italic;">// 组件实例</span></span>
<span class="line"><span style="color:#C792EA;">const</span><span style="color:#A6ACCD;"> instance </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#89DDFF;">  </span><span style="color:#676E95;font-style:italic;">// ....</span></span>
<span class="line"><span style="color:#A6ACCD;">  parent</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#676E95;font-style:italic;">// 标记当前组件的父亲是谁</span></span>
<span class="line"><span style="color:#A6ACCD;">  </span><span style="color:#F07178;">provides</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> parent </span><span style="color:#89DDFF;">?</span><span style="color:#A6ACCD;"> parent</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">provides </span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> Object</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">create</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">null</span><span style="color:#A6ACCD;">)</span><span style="color:#89DDFF;">,</span></span>
<span class="line"><span style="color:#89DDFF;">};</span></span></code></pre></div><div class="language-js"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#89DDFF;font-style:italic;">import</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">currentInstance</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;font-style:italic;">as</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">instance</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">}</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;font-style:italic;">from</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">./component</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;">/**</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;"> * 内容提供者</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;"> * </span><span style="color:#89DDFF;font-style:italic;">@</span><span style="color:#C792EA;font-style:italic;">param</span><span style="color:#676E95;font-style:italic;"> </span><span style="color:#A6ACCD;font-style:italic;">key</span><span style="color:#676E95;font-style:italic;"> 消费的key</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;"> * </span><span style="color:#89DDFF;font-style:italic;">@</span><span style="color:#C792EA;font-style:italic;">param</span><span style="color:#676E95;font-style:italic;"> </span><span style="color:#A6ACCD;font-style:italic;">value</span><span style="color:#676E95;font-style:italic;"> 消费的值</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;"> * </span><span style="color:#89DDFF;font-style:italic;">@</span><span style="color:#C792EA;font-style:italic;">returns</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;"> */</span></span>
<span class="line"><span style="color:#89DDFF;font-style:italic;">export</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">function</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">provide</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;font-style:italic;">key</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#A6ACCD;font-style:italic;">value</span><span style="color:#89DDFF;">)</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;font-style:italic;">if</span><span style="color:#F07178;"> (</span><span style="color:#89DDFF;">!</span><span style="color:#A6ACCD;">instance</span><span style="color:#F07178;">) </span><span style="color:#89DDFF;font-style:italic;">return</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#C792EA;">let</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">parentProvides</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">instance</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">parent</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">&amp;&amp;</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">instance</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">parent</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">provides</span><span style="color:#89DDFF;">;</span><span style="color:#F07178;"> </span><span style="color:#676E95;font-style:italic;">// 父组件的provides</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#C792EA;">let</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">currentProvides</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">instance</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">provides</span><span style="color:#89DDFF;">;</span><span style="color:#F07178;"> </span><span style="color:#676E95;font-style:italic;">// 当前节点的provides</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;font-style:italic;">if</span><span style="color:#F07178;"> (</span><span style="color:#A6ACCD;">currentProvides</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">===</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">parentProvides</span><span style="color:#F07178;">) </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#A6ACCD;">currentProvides</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">instance</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">provides</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">Object</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">create</span><span style="color:#F07178;">(</span><span style="color:#A6ACCD;">parentProvides</span><span style="color:#F07178;">)</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#A6ACCD;">currentProvides</span><span style="color:#F07178;">[</span><span style="color:#A6ACCD;">key</span><span style="color:#F07178;">] </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">value</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#676E95;font-style:italic;">/**</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;"> * 消费者</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;"> * </span><span style="color:#89DDFF;font-style:italic;">@</span><span style="color:#C792EA;font-style:italic;">param</span><span style="color:#676E95;font-style:italic;"> </span><span style="color:#A6ACCD;font-style:italic;">key</span><span style="color:#676E95;font-style:italic;"> 内容提供者key</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;"> * </span><span style="color:#89DDFF;font-style:italic;">@</span><span style="color:#C792EA;font-style:italic;">param</span><span style="color:#676E95;font-style:italic;"> </span><span style="color:#A6ACCD;font-style:italic;">defaultValue</span><span style="color:#676E95;font-style:italic;"> 默认值</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;"> * </span><span style="color:#89DDFF;font-style:italic;">@</span><span style="color:#C792EA;font-style:italic;">returns</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;"> */</span></span>
<span class="line"><span style="color:#89DDFF;font-style:italic;">export</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">function</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">inject</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;font-style:italic;">key</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#A6ACCD;font-style:italic;">defaultValue</span><span style="color:#89DDFF;">)</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;font-style:italic;">if</span><span style="color:#F07178;"> (</span><span style="color:#89DDFF;">!</span><span style="color:#A6ACCD;">instance</span><span style="color:#F07178;">) </span><span style="color:#89DDFF;font-style:italic;">return</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#89DDFF;">  </span><span style="color:#676E95;font-style:italic;">// 取组件提供的provide，如果没有返回默认值</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#C792EA;">const</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">provides</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">instance</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">parent</span><span style="color:#89DDFF;">?.</span><span style="color:#A6ACCD;">provides</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;font-style:italic;">if</span><span style="color:#F07178;"> (</span><span style="color:#A6ACCD;">provides</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">&amp;&amp;</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">key</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">in</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">provides</span><span style="color:#F07178;">) </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#89DDFF;font-style:italic;">return</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">provides</span><span style="color:#F07178;">[</span><span style="color:#A6ACCD;">key</span><span style="color:#F07178;">]</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;">}</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;font-style:italic;">else</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#89DDFF;font-style:italic;">return</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">defaultValue</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span></code></pre></div><h2 id="vue-diff" tabindex="-1">Vue diff <a class="header-anchor" href="#vue-diff" aria-label="Permalink to &quot;Vue diff&quot;">​</a></h2><ul><li><p>Vue 的 diff 算法是平级比较，不考虑跨级比较的情况。内部采用深度递归的方式 + 单指针的方式进行比较。</p></li><li><p>优化策略有 3 种，头头、尾尾、乱序</p></li><li><p>都是先比较是否是相同节点，相同节点比较属性,并复用老节点，比较儿子节点</p></li><li><p>1、<code>头头对比</code>新老虚拟节点进行头头对比，如果 tag、key 相同，复用老的节点，比较儿子节点，头指针索引递增</p></li><li><p>2、<code>尾尾开始对比</code>，如果 tag、key 相同新老尾指针递减</p></li><li><p>3、如果头指针超过其中有任何一个尾指针，证明有一方已经对比完毕，停止循环</p></li><li><p>4、如果老的虚拟节点没有对比完全部删除</p></li><li><p>5、如果新的虚拟节点没有对比完讲新的插入(头指针索引递增)</p></li><li><p>6、如果新老虚拟节头头、尾尾对比之后都没对比完成，可能中间的节点可以复用</p></li><li><p>7、<code>乱序对比</code>,需要尽可能复用，用新的虚拟列表做成一个映射表</p></li><li><p>8、遍历老的虚拟列表，如果如果 key 相同标记已复用，如果不相同，删除老的节点</p></li><li><p>9、最后插入新的元素，移动复用的元素到正确的位置</p></li></ul><h3 id="_1、头头对比" tabindex="-1">1、头头对比 <a class="header-anchor" href="#_1、头头对比" aria-label="Permalink to &quot;1、头头对比&quot;">​</a></h3><p><img src="/fe-handbook/document/assets/vue3-top-diif.aab7bf7b.png" alt="diff"></p><h3 id="_2、尾尾对比" tabindex="-1">2、尾尾对比 <a class="header-anchor" href="#_2、尾尾对比" aria-label="Permalink to &quot;2、尾尾对比&quot;">​</a></h3><p><img src="/fe-handbook/document/assets/vue3-tail-diif.e8d91ad3.png" alt="diff"></p><h3 id="_3、乱序对比" tabindex="-1">3、乱序对比 <a class="header-anchor" href="#_3、乱序对比" aria-label="Permalink to &quot;3、乱序对比&quot;">​</a></h3><p><img src="/fe-handbook/document/assets/vue3-middle-diff.5db8f73f.png" alt="diff"></p><h3 id="life-cycle-生命周期" tabindex="-1">life cycle(生命周期) <a class="header-anchor" href="#life-cycle-生命周期" aria-label="Permalink to &quot;life cycle(生命周期)&quot;">​</a></h3><ul><li><p>通过发布/订阅来实现收集、触发</p></li><li><p>1、vue3 生命周期必须在 setup 中使用，并且生命周期 hook 存储在当前组件的实例上</p></li><li><p>2、组件在初始化时，如果有 setup 函数，会存储当前组件的实例，并且会导出</p></li><li><p>3、在执行 setup 函数时，如果有钩子函数，会进行分类，并且生命周期 hook 会存储在当前组件的实例上</p></li><li><p>4、当组件渲染到某一个阶段时，会从当前组件的实例上去查找对应的生命周期 hook 并且执行</p></li></ul><blockquote><p>内部执行</p></blockquote><ul><li>1、首先调用 createHook 将函数进行分类，并且返回生命周期钩子函数</li><li>2、当生命周期钩子函数在执行时，会传递一个 hook 函数，还有一个默认值(当前组件实例)</li><li>3、此时会调用 injectHook 进行收集，并且会传递三个参数(生命周期类型、hook 函数、当前组件实例)</li><li>4、injectHook 内部会看当前实例上，有没有同类型的 hook，如果没有先创建在新增，如果有直接新增</li><li>5、因为 hook 在执行时，始终需要获取到当前组件的实例，这里 hook 在保存的时候会进行 AOP 拦截，在 hook 执行前，设置正确的组件实例，当 hook 执行完成后，将当前的实例设置为 null</li></ul><div class="language-js"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#89DDFF;font-style:italic;">import</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">currentInstance</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">setCurrentInstance</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">}</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;font-style:italic;">from</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">./component</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#C792EA;">const</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">enum</span><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">LifeCycles</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">  BEFORE_MOUNT </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">bm</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#676E95;font-style:italic;">// 组件渲染前</span></span>
<span class="line"><span style="color:#A6ACCD;">  MOUNTED </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">m</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#676E95;font-style:italic;">// 组件渲染后</span></span>
<span class="line"><span style="color:#A6ACCD;">  BEFORE_UPDATE </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">bu</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#676E95;font-style:italic;">// 组件更新前</span></span>
<span class="line"><span style="color:#A6ACCD;">  UPDATED </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">u</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#676E95;font-style:italic;">// 组件更新后</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;">// 生命周期只能在setup中使用</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;">// 因为只有在调用setup时才会生成组件的实例，currentInstance，并且生命周期挂载组件实例上</span></span>
<span class="line"></span>
<span class="line"><span style="color:#676E95;font-style:italic;">// 订阅</span></span>
<span class="line"><span style="color:#C792EA;">function</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">createHook</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;"> </span><span style="color:#A6ACCD;font-style:italic;">lifeCycle</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">)</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#676E95;font-style:italic;">/**</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;">   * hook v钩子类型</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;">   * currentInstance 当前组件的实例</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;">   */</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;font-style:italic;">return</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">(</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;font-style:italic;">hook</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;font-style:italic;">target</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">currentInstance</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">)</span><span style="color:#F07178;"> </span><span style="color:#C792EA;">=&gt;</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#82AAFF;">injectHook</span><span style="color:#F07178;">( </span><span style="color:#A6ACCD;">lifeCycle</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">hook</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">target</span><span style="color:#F07178;"> )</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;">};</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#C792EA;">function</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">injectHook</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;"> </span><span style="color:#A6ACCD;font-style:italic;">lifecycle</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#A6ACCD;font-style:italic;">hook</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#A6ACCD;font-style:italic;">target</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">)</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;font-style:italic;">if</span><span style="color:#F07178;"> ( </span><span style="color:#89DDFF;">!</span><span style="color:#A6ACCD;">target</span><span style="color:#F07178;"> ) </span><span style="color:#89DDFF;font-style:italic;">return</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#89DDFF;">  </span><span style="color:#676E95;font-style:italic;">// 一个组件同一类型生命周期可以多个</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#C792EA;">const</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">hooks</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">target</span><span style="color:#F07178;">[</span><span style="color:#A6ACCD;">lifecycle</span><span style="color:#F07178;">] </span><span style="color:#89DDFF;">||</span><span style="color:#F07178;"> ( </span><span style="color:#A6ACCD;">target</span><span style="color:#F07178;">[</span><span style="color:#A6ACCD;">lifecycle</span><span style="color:#F07178;">] </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> [] )</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#C792EA;">const</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">wrap</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">()</span><span style="color:#F07178;"> </span><span style="color:#C792EA;">=&gt;</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#82AAFF;">setCurrentInstance</span><span style="color:#F07178;">( </span><span style="color:#A6ACCD;">target</span><span style="color:#F07178;"> )</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#82AAFF;">hook</span><span style="color:#F07178;">()</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#82AAFF;">setCurrentInstance</span><span style="color:#F07178;">( </span><span style="color:#89DDFF;">null</span><span style="color:#F07178;"> )</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;">};</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#A6ACCD;">hooks</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">push</span><span style="color:#F07178;">( </span><span style="color:#A6ACCD;">wrap</span><span style="color:#F07178;"> )</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#676E95;font-style:italic;">// 发布</span></span>
<span class="line"><span style="color:#89DDFF;font-style:italic;">export</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">function</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">invokeArrayFns</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;"> </span><span style="color:#A6ACCD;font-style:italic;">fns</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">)</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#A6ACCD;">fns</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">forEach</span><span style="color:#F07178;">( </span><span style="color:#89DDFF;">(</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;font-style:italic;">fn</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">)</span><span style="color:#F07178;"> </span><span style="color:#C792EA;">=&gt;</span><span style="color:#F07178;"> </span><span style="color:#82AAFF;">fn</span><span style="color:#F07178;">() )</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#89DDFF;font-style:italic;">export</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">const</span><span style="color:#A6ACCD;"> onBeforeMount </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">createHook</span><span style="color:#A6ACCD;">( LifeCycles</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">BEFORE_MOUNT )</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#89DDFF;font-style:italic;">export</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">const</span><span style="color:#A6ACCD;"> onMounted </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">createHook</span><span style="color:#A6ACCD;">( LifeCycles</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">MOUNTED )</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#89DDFF;font-style:italic;">export</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">const</span><span style="color:#A6ACCD;"> onBeforeUpdate </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">createHook</span><span style="color:#A6ACCD;">( LifeCycles</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">BEFORE_UPDATE )</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#89DDFF;font-style:italic;">export</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">const</span><span style="color:#A6ACCD;"> onUpdated </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">createHook</span><span style="color:#A6ACCD;">( LifeCycles</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">UPDATED )</span><span style="color:#89DDFF;">;</span></span></code></pre></div><h2 id="keepalive" tabindex="-1">keepAlive <a class="header-anchor" href="#keepalive" aria-label="Permalink to &quot;keepAlive&quot;">​</a></h2><div class="tip custom-block"><p class="custom-block-title">TIP</p><p>keepAlive 主要的作用就是将组件进行缓存，提高渲染性能</p></div><ul><li>1、默认渲染 keep-alive 中插槽内容， 检测插槽是不是组件</li><li>2、如果是组件就把组件和对应的 key 做成一个映射表，缓存起来</li><li>3、卸载组件挂载新的组件，此时会命中插槽的更新， 卸载老组件的时候不是真的卸载，而是缓存到 dom 中。 加载新的组件</li><li>4、下次访问的是已经访问过的组件了，那么此时需要复用组件的实例，并且不要在初始化了</li><li>5、初始化的时候 会在缓存区中将 dom 拉取到容器中 “缓存的是 dom”</li><li>6、缓存策略可以采用 lru 算法，实现删除头部，最新访问的放在尾部</li></ul><div class="language-js"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#89DDFF;font-style:italic;">import</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">onMounted</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">onUpdated</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">}</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;font-style:italic;">from</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">./apiLifecycle</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#89DDFF;font-style:italic;">import</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">getCurrentInstance</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">}</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;font-style:italic;">from</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">./component</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#89DDFF;font-style:italic;">import</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">ShapeFlags</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">}</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;font-style:italic;">from</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">@vue/shared</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#C792EA;">function</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">resetFlag</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;font-style:italic;">vnode</span><span style="color:#89DDFF;">)</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;font-style:italic;">if</span><span style="color:#F07178;"> (</span><span style="color:#A6ACCD;">vnode</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">shapeFlag</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">&amp;</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">ShapeFlags</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">COMPONENT_KEPT_ALIVE</span><span style="color:#F07178;">) </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#A6ACCD;">vnode</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">shapeFlag</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">-=</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">ShapeFlags</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">COMPONENT_KEPT_ALIVE</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;font-style:italic;">if</span><span style="color:#F07178;"> (</span><span style="color:#A6ACCD;">vnode</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">shapeFlag</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">&amp;</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">ShapeFlags</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">COMPONENT_SHOULD_KEEP_ALIVE</span><span style="color:#F07178;">) </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#A6ACCD;">vnode</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">shapeFlag</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">-=</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">ShapeFlags</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">COMPONENT_SHOULD_KEEP_ALIVE</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#89DDFF;font-style:italic;">export</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">const</span><span style="color:#A6ACCD;"> KeepAlive </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">  </span><span style="color:#F07178;">__isKeepAlive</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#FF9CAC;">true</span><span style="color:#89DDFF;">,</span></span>
<span class="line"><span style="color:#A6ACCD;">  </span><span style="color:#F07178;">props</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#F07178;">max</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{},</span></span>
<span class="line"><span style="color:#A6ACCD;">  </span><span style="color:#89DDFF;">},</span></span>
<span class="line"><span style="color:#A6ACCD;">  </span><span style="color:#F07178;">setup</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;font-style:italic;">props</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span><span style="color:#A6ACCD;"> </span><span style="color:#A6ACCD;font-style:italic;">slots</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">})</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#89DDFF;">    </span><span style="color:#676E95;font-style:italic;">// dom操作api都在instance.ctx.renderer上面</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#C792EA;">const</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">instance</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#82AAFF;">getCurrentInstance</span><span style="color:#F07178;">()</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#C792EA;">let</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">{</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">createElement</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">move</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">}</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">instance</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">ctx</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">renderer</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#C792EA;">const</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">keys</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">new</span><span style="color:#F07178;"> </span><span style="color:#82AAFF;">Set</span><span style="color:#F07178;">()</span><span style="color:#89DDFF;">;</span><span style="color:#F07178;"> </span><span style="color:#676E95;font-style:italic;">// 缓存组件的key</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#C792EA;">const</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">cache</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">new</span><span style="color:#F07178;"> </span><span style="color:#82AAFF;">Map</span><span style="color:#F07178;">()</span><span style="color:#89DDFF;">;</span><span style="color:#F07178;"> </span><span style="color:#676E95;font-style:italic;">// 缓存组件的映射关系</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#C792EA;">const</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">pruneCacheEntry</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;font-style:italic;">vnode</span><span style="color:#89DDFF;">)</span><span style="color:#F07178;"> </span><span style="color:#C792EA;">=&gt;</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">      </span><span style="color:#C792EA;">const</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">subTree</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">cache</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">get</span><span style="color:#F07178;">(</span><span style="color:#A6ACCD;">vnode</span><span style="color:#F07178;">)</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#F07178;">      </span><span style="color:#82AAFF;">resetFlag</span><span style="color:#F07178;">(</span><span style="color:#A6ACCD;">subTree</span><span style="color:#F07178;">)</span><span style="color:#89DDFF;">;</span><span style="color:#F07178;"> </span><span style="color:#676E95;font-style:italic;">// 移除keep-alive标记</span></span>
<span class="line"><span style="color:#F07178;">      </span><span style="color:#A6ACCD;">cache</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">delete</span><span style="color:#F07178;">(</span><span style="color:#A6ACCD;">vnode</span><span style="color:#F07178;">)</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#F07178;">      </span><span style="color:#A6ACCD;">keys</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">delete</span><span style="color:#F07178;">(</span><span style="color:#A6ACCD;">vnode</span><span style="color:#F07178;">)</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#89DDFF;">};</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#C792EA;">let</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">storageContainer</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#82AAFF;">createElement</span><span style="color:#F07178;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">div</span><span style="color:#89DDFF;">&quot;</span><span style="color:#F07178;">)</span><span style="color:#89DDFF;">;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#89DDFF;">    </span><span style="color:#676E95;font-style:italic;">// 有缓存</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#A6ACCD;">instance</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">ctx</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">active</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;font-style:italic;">n2</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;font-style:italic;">container</span><span style="color:#89DDFF;">)</span><span style="color:#F07178;"> </span><span style="color:#C792EA;">=&gt;</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">      </span><span style="color:#82AAFF;">move</span><span style="color:#F07178;">(</span><span style="color:#A6ACCD;">n2</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">container</span><span style="color:#F07178;">)</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#89DDFF;">};</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#A6ACCD;">instance</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">ctx</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">deactivate</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;font-style:italic;">n1</span><span style="color:#89DDFF;">)</span><span style="color:#F07178;"> </span><span style="color:#C792EA;">=&gt;</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#89DDFF;">      </span><span style="color:#676E95;font-style:italic;">// 组件卸载的时候 会将虚拟节点对应的真实节点，移动到容器中</span></span>
<span class="line"><span style="color:#F07178;">      </span><span style="color:#82AAFF;">move</span><span style="color:#F07178;">(</span><span style="color:#A6ACCD;">n1</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">storageContainer</span><span style="color:#F07178;">)</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#89DDFF;">};</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#C792EA;">let</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">pendingCacheKey</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">null;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#C792EA;">const</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">cacheSubTree</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">()</span><span style="color:#F07178;"> </span><span style="color:#C792EA;">=&gt;</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">      </span><span style="color:#A6ACCD;">cache</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">set</span><span style="color:#F07178;">(</span><span style="color:#A6ACCD;">pendingCacheKey</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">instance</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">subTree</span><span style="color:#F07178;">)</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#89DDFF;">};</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#82AAFF;">onMounted</span><span style="color:#F07178;">(</span><span style="color:#A6ACCD;">cacheSubTree</span><span style="color:#F07178;">)</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#82AAFF;">onUpdated</span><span style="color:#F07178;">(</span><span style="color:#A6ACCD;">cacheSubTree</span><span style="color:#F07178;">)</span><span style="color:#89DDFF;">;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#89DDFF;font-style:italic;">return</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">()</span><span style="color:#F07178;"> </span><span style="color:#C792EA;">=&gt;</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">      </span><span style="color:#C792EA;">let</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">vnode</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">slots</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">default</span><span style="color:#F07178;">()</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#89DDFF;">      </span><span style="color:#676E95;font-style:italic;">// 不是组件就不用缓存了</span></span>
<span class="line"><span style="color:#F07178;">      </span><span style="color:#89DDFF;font-style:italic;">if</span><span style="color:#F07178;"> (</span><span style="color:#89DDFF;">!</span><span style="color:#F07178;">(</span><span style="color:#A6ACCD;">vnode</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">shapeFlag</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">&amp;</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">ShapeFlags</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">STATEFUL_COMPONENT</span><span style="color:#F07178;">)) </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">        </span><span style="color:#89DDFF;font-style:italic;">return</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">vnode</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#F07178;">      </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#F07178;">      </span><span style="color:#C792EA;">let</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">comp</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">vnode</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">type</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#89DDFF;">      </span><span style="color:#676E95;font-style:italic;">// 组件的名字  找 name，找key ，找组件本身</span></span>
<span class="line"><span style="color:#F07178;">      </span><span style="color:#C792EA;">let</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">key</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">vnode</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">key</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">==</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">null</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">?</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">comp</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">:</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">vnode</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">key</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#F07178;">      </span><span style="color:#A6ACCD;">pendingCacheKey</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">key</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#F07178;">      </span><span style="color:#C792EA;">let</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">cacheVnode</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">cache</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">get</span><span style="color:#F07178;">(</span><span style="color:#A6ACCD;">key</span><span style="color:#F07178;">)</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#F07178;">      </span><span style="color:#89DDFF;font-style:italic;">if</span><span style="color:#F07178;"> (</span><span style="color:#A6ACCD;">cacheVnode</span><span style="color:#F07178;">) </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#89DDFF;">        </span><span style="color:#676E95;font-style:italic;">// 走到缓存里需要干什么？</span></span>
<span class="line"><span style="color:#F07178;">        </span><span style="color:#A6ACCD;">vnode</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">component</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">cacheVnode</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">component</span><span style="color:#89DDFF;">;</span><span style="color:#F07178;"> </span><span style="color:#676E95;font-style:italic;">// 复用组件</span></span>
<span class="line"><span style="color:#F07178;">        </span><span style="color:#A6ACCD;">vnode</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">shapeFlag</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">|=</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">ShapeFlags</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">COMPONENT_KEPT_ALIVE</span><span style="color:#89DDFF;">;</span><span style="color:#F07178;"> </span><span style="color:#676E95;font-style:italic;">// 组件走缓存的时候不要初始化</span></span>
<span class="line"><span style="color:#F07178;">      </span><span style="color:#89DDFF;">}</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;font-style:italic;">else</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">        </span><span style="color:#A6ACCD;">keys</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">add</span><span style="color:#F07178;">(</span><span style="color:#A6ACCD;">key</span><span style="color:#F07178;">)</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#F07178;">        </span><span style="color:#C792EA;">let</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">{</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">max</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">}</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">props</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#F07178;">        </span><span style="color:#89DDFF;font-style:italic;">if</span><span style="color:#F07178;"> (</span><span style="color:#A6ACCD;">max</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">&amp;&amp;</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">keys</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">size</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">&gt;</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">max</span><span style="color:#F07178;">) </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#89DDFF;">          </span><span style="color:#676E95;font-style:italic;">// 删除第一个元素 ，在最后增加</span></span>
<span class="line"><span style="color:#89DDFF;">          </span><span style="color:#676E95;font-style:italic;">// next 返回的是一个对象 {value,done}</span></span>
<span class="line"><span style="color:#F07178;">          </span><span style="color:#82AAFF;">pruneCacheEntry</span><span style="color:#F07178;">(</span><span style="color:#A6ACCD;">keys</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">values</span><span style="color:#F07178;">()</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">next</span><span style="color:#F07178;">()</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">value</span><span style="color:#F07178;">)</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#F07178;">        </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#89DDFF;">        </span><span style="color:#676E95;font-style:italic;">// 获取到了虚拟节点</span></span>
<span class="line"><span style="color:#F07178;">      </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#F07178;">      </span><span style="color:#A6ACCD;">vnode</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">shapeFlag</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">|=</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">ShapeFlags</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">COMPONENT_SHOULD_KEEP_ALIVE</span><span style="color:#89DDFF;">;</span><span style="color:#F07178;"> </span><span style="color:#676E95;font-style:italic;">// 用来告诉这个vnode稍后卸载的时候 应该缓存起来</span></span>
<span class="line"><span style="color:#89DDFF;">      </span><span style="color:#676E95;font-style:italic;">// 组件还是会重新创建, 会走mountComponent</span></span>
<span class="line"><span style="color:#F07178;">      </span><span style="color:#89DDFF;font-style:italic;">return</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">vnode</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#89DDFF;">};</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;">},</span></span>
<span class="line"><span style="color:#89DDFF;">};</span></span></code></pre></div><div class="language-js"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#676E95;font-style:italic;">// -------------------组件----------------------</span></span>
<span class="line"><span style="color:#676E95;font-style:italic;">// 走缓存</span></span>
<span class="line"><span style="color:#C792EA;">function</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">processComponent</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;font-style:italic;">n1</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#A6ACCD;font-style:italic;">n2</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#A6ACCD;font-style:italic;">container</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#A6ACCD;font-style:italic;">parent</span><span style="color:#89DDFF;">)</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;font-style:italic;">if</span><span style="color:#F07178;"> (</span><span style="color:#A6ACCD;">n1</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">==</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">null</span><span style="color:#F07178;">) </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#89DDFF;font-style:italic;">if</span><span style="color:#F07178;"> (</span><span style="color:#A6ACCD;">n2</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">shapeFlag</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">&amp;</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">ShapeFlags</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">COMPONENT_KEPT_ALIVE</span><span style="color:#F07178;">) </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#89DDFF;">      </span><span style="color:#676E95;font-style:italic;">// 在第一次卸载的时候，我们已经将dom元素移动到内存中，这次渲染我们再将他拿回来</span></span>
<span class="line"><span style="color:#F07178;">      </span><span style="color:#A6ACCD;">parent</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">ctx</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">active</span><span style="color:#F07178;">(</span><span style="color:#A6ACCD;">n2</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">container</span><span style="color:#F07178;">)</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#89DDFF;">}</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;font-style:italic;">else</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#89DDFF;">      </span><span style="color:#676E95;font-style:italic;">// 初次渲染</span></span>
<span class="line"><span style="color:#F07178;">      </span><span style="color:#82AAFF;">mountComponent</span><span style="color:#F07178;">(</span><span style="color:#A6ACCD;">n2</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">container</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">parent</span><span style="color:#F07178;">)</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;">}</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;font-style:italic;">else</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#A6ACCD;">console</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">log</span><span style="color:#F07178;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">组件更新</span><span style="color:#89DDFF;">&quot;</span><span style="color:#F07178;">)</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span></code></pre></div><div class="language-js"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#676E95;font-style:italic;">// 删除老的节点</span></span>
<span class="line"><span style="color:#C792EA;">function</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">unmount</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;font-style:italic;">n1</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#A6ACCD;font-style:italic;">parent</span><span style="color:#89DDFF;">)</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#C792EA;">let</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">{</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">shapeFlag</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">}</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">n1</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#89DDFF;">  </span><span style="color:#676E95;font-style:italic;">// 被缓存的组件不会真实卸载，而是存储在内存中，下次渲染的时候，直接在内存中取</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;font-style:italic;">if</span><span style="color:#F07178;"> (</span><span style="color:#A6ACCD;">shapeFlag</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">&amp;</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">ShapeFlags</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">COMPONENT_SHOULD_KEEP_ALIVE</span><span style="color:#F07178;">) </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#A6ACCD;">parent</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">ctx</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">deactivate</span><span style="color:#F07178;">(</span><span style="color:#A6ACCD;">n1</span><span style="color:#F07178;">)</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;">}</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;font-style:italic;">else</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#89DDFF;">    </span><span style="color:#676E95;font-style:italic;">// 如果是组件 调用的组件的生命周期等(组件情况)</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#82AAFF;">hostRemove</span><span style="color:#F07178;">(</span><span style="color:#A6ACCD;">n1</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">el</span><span style="color:#F07178;">)</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span></code></pre></div><h2 id="nexttick" tabindex="-1">nextTick <a class="header-anchor" href="#nexttick" aria-label="Permalink to &quot;nextTick&quot;">​</a></h2><ul><li>Vue 中视图更新是异步的，使用 nextTick 方法可以保证用户定义的逻辑在更新之后执行,可用于获取更新后的 DOM，多次调用 nextTick 会被合并</li><li>在调用nextTick时，不会立马执行回调，而是存储在队列中，同步任务全部执行完毕后，批量更新，DOM更新的任务也是调用的nextTick</li></ul><div class="language-js"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#676E95;font-style:italic;">// 简化版 Vue 3 的 nextTick 源码</span></span>
<span class="line"><span style="color:#C792EA;">const</span><span style="color:#A6ACCD;"> schedulerQueue </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> []</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> isFlushing </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#FF9CAC;">false</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#C792EA;">function</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">flushSchedulerQueue</span><span style="color:#89DDFF;">()</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#A6ACCD;">isFlushing</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#FF9CAC;">true</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#C792EA;">const</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">currentQueue</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">schedulerQueue</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">slice</span><span style="color:#F07178;">()</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#A6ACCD;">schedulerQueue</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">length</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#F78C6C;">0</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#A6ACCD;">isFlushing</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#FF9CAC;">false</span><span style="color:#89DDFF;">;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;font-style:italic;">for</span><span style="color:#F07178;"> (</span><span style="color:#C792EA;">const</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">job</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">of</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">currentQueue</span><span style="color:#F07178;">) </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#82AAFF;">job</span><span style="color:#F07178;">()</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#C792EA;">function</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">queueJob</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;font-style:italic;">job</span><span style="color:#89DDFF;">)</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;font-style:italic;">if</span><span style="color:#F07178;"> (</span><span style="color:#89DDFF;">!</span><span style="color:#A6ACCD;">schedulerQueue</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">includes</span><span style="color:#F07178;">(</span><span style="color:#A6ACCD;">job</span><span style="color:#F07178;">)) </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#A6ACCD;">schedulerQueue</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">push</span><span style="color:#F07178;">(</span><span style="color:#A6ACCD;">job</span><span style="color:#F07178;">)</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#89DDFF;font-style:italic;">if</span><span style="color:#F07178;"> (</span><span style="color:#89DDFF;">!</span><span style="color:#A6ACCD;">isFlushing</span><span style="color:#F07178;">) </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">      </span><span style="color:#FFCB6B;">Promise</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">resolve</span><span style="color:#F07178;">()</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">then</span><span style="color:#F07178;">(</span><span style="color:#A6ACCD;">flushSchedulerQueue</span><span style="color:#F07178;">)</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#C792EA;">function</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">nextTick</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;font-style:italic;">callback</span><span style="color:#89DDFF;">)</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#82AAFF;">queueJob</span><span style="color:#F07178;">(</span><span style="color:#A6ACCD;">callback</span><span style="color:#F07178;">)</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#676E95;font-style:italic;">// 示例用法</span></span>
<span class="line"><span style="color:#82AAFF;">nextTick</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">()</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">=&gt;</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#A6ACCD;">console</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">log</span><span style="color:#F07178;">(</span><span style="color:#89DDFF;">&#39;</span><span style="color:#C3E88D;">Next tick callback</span><span style="color:#89DDFF;">&#39;</span><span style="color:#F07178;">)</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#89DDFF;">}</span><span style="color:#A6ACCD;">)</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#A6ACCD;">console</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">log</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">&#39;</span><span style="color:#C3E88D;">End of main script</span><span style="color:#89DDFF;">&#39;</span><span style="color:#A6ACCD;">)</span><span style="color:#89DDFF;">;</span></span></code></pre></div><h2 id="nexttick一定会拿到更新之后的dom属性吗" tabindex="-1">nextTick一定会拿到更新之后的DOM属性吗 <a class="header-anchor" href="#nexttick一定会拿到更新之后的dom属性吗" aria-label="Permalink to &quot;nextTick一定会拿到更新之后的DOM属性吗&quot;">​</a></h2><ul><li>这个是不确定的，这个取决于<code>nextTick</code>的调用时机，是否在响应式数据发生改变之后</li><li>原理： <ul><li>因为响应式数据发生改变后，会触发试图异步更新，低层也是调用的<code>nextTick</code>加入到队列中</li><li>如果nextTick调用时机在响应式数据发生改变之前，会在视图更新之前执行，所以获取domRef.value.innerHTML，获取到还是老的值</li></ul></li></ul><div class="language-js"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#C792EA;">const</span><span style="color:#A6ACCD;"> domRef </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">ref</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">null</span><span style="color:#A6ACCD;">)</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#C792EA;">const</span><span style="color:#A6ACCD;"> state </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">ref</span><span style="color:#A6ACCD;">(</span><span style="color:#F78C6C;">0</span><span style="color:#A6ACCD;">)</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#82AAFF;">nextTick</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">()</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">=&gt;</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#A6ACCD;">console</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">log</span><span style="color:#F07178;">(</span><span style="color:#A6ACCD;">domRef</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">value</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">innerHTML</span><span style="color:#F07178;">)</span><span style="color:#89DDFF;">;</span><span style="color:#F07178;"> </span><span style="color:#676E95;font-style:italic;">// 0 </span></span>
<span class="line"><span style="color:#89DDFF;">}</span><span style="color:#A6ACCD;">)</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#A6ACCD;">state</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">value </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">1</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#82AAFF;">nextTick</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">()</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">=&gt;</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#A6ACCD;">console</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">log</span><span style="color:#F07178;">(</span><span style="color:#A6ACCD;">domRef</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">value</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">innerHTML</span><span style="color:#F07178;">)</span><span style="color:#89DDFF;">;</span><span style="color:#F07178;"> </span><span style="color:#676E95;font-style:italic;">// 1</span></span>
<span class="line"><span style="color:#89DDFF;">}</span><span style="color:#A6ACCD;">)</span><span style="color:#89DDFF;">;</span></span></code></pre></div><h2 id="vue2为什么只能有一个根节点-vue3可以多根节点" tabindex="-1">vue2为什么只能有一个根节点，vue3可以多根节点？ <a class="header-anchor" href="#vue2为什么只能有一个根节点-vue3可以多根节点" aria-label="Permalink to &quot;vue2为什么只能有一个根节点，vue3可以多根节点？&quot;">​</a></h2><ul><li><p><code>因为vue2</code>vdom是一个单根树形结构描述当前视图结构，patch方法在遍历的时候从根节点开始遍历，它要求只有一个根节点。组件也是会转换成vdom，所以也必须满足单根节点要求</p></li><li><p><code>因为vue3</code>引入了fragment概念，这是一个抽象的节点，如果发现组件是多根的会自动创建一个fragment节点，把多根节点视为自己的children。在patch时，如果发现这是一个fragment节点，则直接遍历children创建或更新</p></li></ul><h2 id="vue-通过数据劫持可以精准探测数据变化-为什么还需要虚拟-dom-进行-diff-检测差异" tabindex="-1">Vue 通过数据劫持可以精准探测数据变化，为什么还需要虚拟 DOM 进行 diff 检测差异? <a class="header-anchor" href="#vue-通过数据劫持可以精准探测数据变化-为什么还需要虚拟-dom-进行-diff-检测差异" aria-label="Permalink to &quot;Vue 通过数据劫持可以精准探测数据变化，为什么还需要虚拟 DOM 进行 diff 检测差异?&quot;">​</a></h2><ul><li>主要是<code>减少DOM的操作</code>，响应式数据发生改变时，组件会生成<code>新的虚拟 DOM</code>，对比两株虚拟 DOM 树的<code>变更差异</code>将更新补丁作用于真实 DOM，以<code>最小</code>成本完成视图更新。</li></ul><h2 id="v-if-v-show" tabindex="-1">v-if&amp;v-show <a class="header-anchor" href="#v-if-v-show" aria-label="Permalink to &quot;v-if&amp;v-show&quot;">​</a></h2><ul><li><code>v-if</code>如果条件不成立，<code>不会渲染</code>当前指令所在的DOM，并且<code>条件为false</code>时组件<code>内部的逻辑</code>不会执行</li><li><code>v-show</code>不管条件是<code>否成立</code>，都会渲染当前指令所在的DOM，映射到DOM就是display<code>block、none</code>，都会执行组件内部逻辑</li></ul><div class="language-js"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#676E95;font-style:italic;">// template</span></span>
<span class="line"><span style="color:#89DDFF;">&lt;</span><span style="color:#F07178;">div</span><span style="color:#89DDFF;"> </span><span style="color:#C792EA;">v-if</span><span style="color:#89DDFF;">=</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">true</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">&gt;</span><span style="color:#A6ACCD;">if的ast</span><span style="color:#89DDFF;">&lt;/</span><span style="color:#F07178;">div</span><span style="color:#89DDFF;">&gt;</span></span>
<span class="line"><span style="color:#89DDFF;">&lt;</span><span style="color:#F07178;">div</span><span style="color:#89DDFF;"> </span><span style="color:#C792EA;">v-show</span><span style="color:#89DDFF;">=</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">true</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">&gt;</span><span style="color:#A6ACCD;">show的ast</span><span style="color:#89DDFF;">&lt;/</span><span style="color:#F07178;">div</span><span style="color:#89DDFF;">&gt;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#676E95;font-style:italic;">// template=&gt;ast</span></span>
<span class="line"><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;font-style:italic;">_ctx</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#A6ACCD;font-style:italic;">_cache</span><span style="color:#89DDFF;">)</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">=&gt;</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;font-style:italic;">return</span><span style="color:#F07178;"> (</span><span style="color:#82AAFF;">_openBlock</span><span style="color:#F07178;">()</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> </span><span style="color:#82AAFF;">_createElementBlock</span><span style="color:#F07178;">(</span><span style="color:#A6ACCD;">_Fragment</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">null,</span><span style="color:#F07178;"> [</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#FF9CAC;">true</span></span>
<span class="line"><span style="color:#F07178;">      </span><span style="color:#89DDFF;">?</span><span style="color:#F07178;"> (</span><span style="color:#82AAFF;">_openBlock</span><span style="color:#F07178;">()</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> </span><span style="color:#82AAFF;">_createElementBlock</span><span style="color:#F07178;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">div</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">_hoisted_1</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">if的ast</span><span style="color:#89DDFF;">&quot;</span><span style="color:#F07178;">))</span></span>
<span class="line"><span style="color:#F07178;">      </span><span style="color:#89DDFF;">:</span><span style="color:#F07178;"> </span><span style="color:#82AAFF;">_createCommentVNode</span><span style="color:#F07178;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">v-if</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> </span><span style="color:#FF9CAC;">true</span><span style="color:#F07178;">)</span><span style="color:#89DDFF;">,</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#82AAFF;">_withDirectives</span><span style="color:#F07178;">(</span><span style="color:#82AAFF;">_createElementVNode</span><span style="color:#F07178;">(</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">div</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">null,</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">show的ast</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> </span><span style="color:#F78C6C;">512</span><span style="color:#F07178;"> </span><span style="color:#676E95;font-style:italic;">/* NEED_PATCH */</span><span style="color:#F07178;">)</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> [</span></span>
<span class="line"><span style="color:#F07178;">      [</span><span style="color:#A6ACCD;">_vShow</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> </span><span style="color:#FF9CAC;">true</span><span style="color:#F07178;">]</span></span>
<span class="line"><span style="color:#F07178;">    ])</span></span>
<span class="line"><span style="color:#F07178;">  ]</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> </span><span style="color:#F78C6C;">64</span><span style="color:#F07178;"> </span><span style="color:#676E95;font-style:italic;">/* STABLE_FRAGMENT */</span><span style="color:#F07178;">))</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span></code></pre></div><h2 id="v-if、v-for优先级" tabindex="-1">v-if、v-for优先级 <a class="header-anchor" href="#v-if、v-for优先级" aria-label="Permalink to &quot;v-if、v-for优先级&quot;">​</a></h2><ul><li>在 Vue2 中解析时，<code>先解析v-for</code>，<code>在解析v-if</code>。会导致先循环后在对每一项进行判断，浪费性能</li><li>在 Vue3 中vif 的优先级高于v-for。</li></ul><h2 id="key的作用" tabindex="-1">key的作用 <a class="header-anchor" href="#key的作用" aria-label="Permalink to &quot;key的作用&quot;">​</a></h2><ul><li>vue中key的主要作用就是，数据在发生变化后，可以通过key和tag节点类型，对比新老Vnode，可以复用老的节点</li><li>尽量不要使用索引到做key</li></ul><!----><h2 id="vue-use是干什么的" tabindex="-1">Vue.use是干什么的 <a class="header-anchor" href="#vue-use是干什么的" aria-label="Permalink to &quot;Vue.use是干什么的&quot;">​</a></h2><ul><li>主要是提供vue插件功能，添加全局的组件、指令等等，</li><li>在提供插件的时候，需要注册一个对象，并且需要有<code>install</code>函数</li></ul><h2 id="vue组件data为什么需要是一个函数" tabindex="-1">Vue组件data为什么需要是一个函数 <a class="header-anchor" href="#vue组件data为什么需要是一个函数" aria-label="Permalink to &quot;Vue组件data为什么需要是一个函数&quot;">​</a></h2><ul><li><code>根实例</code>对象data可以是对象也可以是<code>函数单例</code>，不会产生数据污染情况</li><li><code>组件实例</code>对象 data必须为函数，目的是为了<code>防止多个组件实例对象之间共用一个data</code>，产生数据污染.所以需要通过工厂函数返回全新的 data 作为组件的数据源</li></ul><div class="language-js"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#C792EA;">function</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">Vue</span><span style="color:#89DDFF;">(){}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#A6ACCD;">Vue</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">extend</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">function</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;font-style:italic;">options</span><span style="color:#89DDFF;">){</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#C792EA;">function</span><span style="color:#F07178;"> </span><span style="color:#82AAFF;">Sub</span><span style="color:#89DDFF;">(){</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#89DDFF;">this.</span><span style="color:#A6ACCD;">data</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">this.</span><span style="color:#A6ACCD;">constructor</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">options</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">data</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#A6ACCD;">Sub</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">options</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">options</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;font-style:italic;">return</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">Sub</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> Child </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> Vue</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">extend</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">  </span><span style="color:#F07178;">data</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span><span style="color:#A6ACCD;"> </span><span style="color:#F07178;">name</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">hl</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">},</span></span>
<span class="line"><span style="color:#89DDFF;">}</span><span style="color:#A6ACCD;">)</span></span>
<span class="line"></span>
<span class="line"><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> child1 </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">new</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">Child</span><span style="color:#A6ACCD;">()</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> child2 </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">new</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">Child</span><span style="color:#A6ACCD;">() </span><span style="color:#89DDFF;">;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#A6ACCD;">console</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">log</span><span style="color:#A6ACCD;">(child1</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">data</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">name)</span><span style="color:#89DDFF;">;</span><span style="color:#A6ACCD;"> </span><span style="color:#676E95;font-style:italic;">// hl</span></span>
<span class="line"><span style="color:#A6ACCD;">child1</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">data</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">name </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">lh</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#A6ACCD;">console</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">log</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">&#39;</span><span style="color:#C3E88D;">child1</span><span style="color:#89DDFF;">&#39;</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;">child1</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">data</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">name)</span><span style="color:#89DDFF;">;</span><span style="color:#A6ACCD;"> </span><span style="color:#676E95;font-style:italic;">// lh</span></span>
<span class="line"><span style="color:#A6ACCD;">console</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">log</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">&#39;</span><span style="color:#C3E88D;">child2</span><span style="color:#89DDFF;">&#39;</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;">child2</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">data</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">name)</span><span style="color:#89DDFF;">;</span><span style="color:#A6ACCD;"> </span><span style="color:#676E95;font-style:italic;">// lh</span></span></code></pre></div><h2 id="v-once-的使用场景有哪些" tabindex="-1">v-once 的使用场景有哪些 <a class="header-anchor" href="#v-once-的使用场景有哪些" aria-label="Permalink to &quot;v-once 的使用场景有哪些&quot;">​</a></h2><ul><li><code>v-once</code>是 vue 中内置指令，<code>只渲染元素和组件一次</code>，随后的重新渲染，元素/组件及其所有的子节点<code>将被当作为静态节点直接跳过更新对比</code>。这可以用于优化更新性能</li><li>vue3.2 之后，增加了v-memo指令，通过依赖列表的方式控制页面渲染</li></ul><h2 id="双向绑定实现原理" tabindex="-1">双向绑定实现原理 <a class="header-anchor" href="#双向绑定实现原理" aria-label="Permalink to &quot;双向绑定实现原理&quot;">​</a></h2><ul><li>在vue中双向绑定靠的的<code>v-model指令</code></li><li>1、模版在解析的时候，如果有v-model属性，会转换成<code>input输入事件</code>，同时把绑定的值，赋值给input value属性</li><li>2、当用户输入内容时，会触发input输入事件来更新绑定的数据</li></ul><h2 id="vue-中-sync-修饰符的作用" tabindex="-1">Vue 中.sync 修饰符的作用 <a class="header-anchor" href="#vue-中-sync-修饰符的作用" aria-label="Permalink to &quot;Vue 中.sync 修饰符的作用&quot;">​</a></h2><div class="tip custom-block"><p class="custom-block-title">TIP</p><p>vue3中sync被移除</p></div><ul><li>在有些情况下，我们可能需要对一个 prop 进行双向绑定，这时可以使用<code>.sync来实现</code>。v-mode1默认只双向绑定一个属性，这里就可以通过.sync修饰符绑定多个属性</li></ul><h2 id="自定义指令" tabindex="-1">自定义指令 <a class="header-anchor" href="#自定义指令" aria-label="Permalink to &quot;自定义指令&quot;">​</a></h2><ul><li>方便开发人员对指令的扩展</li></ul><h3 id="指令的生命周期" tabindex="-1">指令的生命周期 <a class="header-anchor" href="#指令的生命周期" aria-label="Permalink to &quot;指令的生命周期&quot;">​</a></h3><ul><li>bind: 只调用一次，指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。</li><li>inserted: 被绑定元素插入父节点时调用(仅保证父节点存在，但不一定已被插入文档中),</li><li>update:所在组件的 VNode 更新时调用，但是可能发生在其子VNode 更新之前，指令的值可能发生了改变，也可能没有。</li><li>componentupdated: 指令所在组件的 VNode 及其子 VNode 全部更新后调用</li><li>unbind: 只调用一次，指令与元素解绑时调用。</li></ul><h2 id="vue-中使用了哪些设计模式" tabindex="-1">Vue 中使用了哪些设计模式 <a class="header-anchor" href="#vue-中使用了哪些设计模式" aria-label="Permalink to &quot;Vue 中使用了哪些设计模式&quot;">​</a></h2><ul><li>单例模式-单例模式就是整个程序有且仅有一个实例 Vuex 中的store。工厂模式-传入参数即可创建实例(createElement)</li><li>发布订阅模式-订阅者把自己想订阅的事件注册到调度中心，当该事件触发时候，发布者发布该事件到调度中心，由调度中心统一调度订阅者注册到调度中心的处理代码。</li><li>观察者模式- watcher&amp;dep的关系</li><li>代理模式-代理模式给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用</li><li>中介者模式。中介者是一个行为设计模式通过提供一个统一的接口让系统的不同部分进行通信。 vuex。策略模式- 策路模式指对象有某个行为,但是在不同的场景中,该行为有不同的实现方案， mergeOption。外观模式-提供了统一的接口，用来访问子系统中的一群接口。</li></ul><h2 id="vue-中的性能优化有哪些" tabindex="-1">Vue 中的性能优化有哪些 <a class="header-anchor" href="#vue-中的性能优化有哪些" aria-label="Permalink to &quot;Vue 中的性能优化有哪些&quot;">​</a></h2><ul><li>数据层级不易过深，合理设置响应式数据</li><li>通过 Object.freeze()方法冻结属性</li><li>使用数据时缓存值的结果，不频繁取值。</li><li>合理设置 Key 属性</li><li>v-show 和v-if 的选取</li><li>控制组件粒度 -&gt; Vue 采用组件级更新</li><li>采用函数式组件-&gt;函数式组件开销低</li><li>采用异步组件-&gt; 借助webpack分包的能力</li><li>使用keep-alive缓存组件v-once</li><li>分页、虚拟滚动、时间分片等策略</li></ul><h2 id="单页应用首屏加载速度慢的怎么解决" tabindex="-1">单页应用首屏加载速度慢的怎么解决 <a class="header-anchor" href="#单页应用首屏加载速度慢的怎么解决" aria-label="Permalink to &quot;单页应用首屏加载速度慢的怎么解决&quot;">​</a></h2><ul><li>使用路由懒加载、异步组件，实现组件拆分，减少入口文件体积大小(优化体验骨架屏)</li><li>抽离公共代码，采用 splitChunks 进行代码分割。</li><li>组件加载采用按需加载的方式。</li><li>静态资源缓存，采用 HTTP 缓存 (强制缓存、对比缓存) 、使用 localStorage 实现缓存资源。</li><li>图片资源的压缩，雪碧图、对小图片进行 base64 减少 http 请求。</li><li>打包时开启 gzip 压缩处理 compression-webpack-plugin 插件</li><li>静态资源采用 CDN 提速。终极的手段</li><li>使用 SSR 对首屏做服务端渲染。</li></ul></div></div></main><footer class="VPDocFooter" data-v-c11df1f0 data-v-fc0d1b73><!--[--><!--]--><div class="edit-info" data-v-fc0d1b73><!----><div class="last-updated" data-v-fc0d1b73><p class="VPLastUpdated" data-v-fc0d1b73 data-v-0de45606>上次更新: <time datetime="2024-02-20T09:50:51.000Z" data-v-0de45606></time></p></div></div><div class="prev-next" data-v-fc0d1b73><div class="pager" data-v-fc0d1b73><a class="pager-link prev" href="/fe-handbook/document/pages/vue/vue2.0.html" data-v-fc0d1b73><span class="desc" data-v-fc0d1b73>Previous page</span><span class="title" data-v-fc0d1b73>vue2.0</span></a></div><div class="has-prev pager" data-v-fc0d1b73><a class="pager-link next" href="/fe-handbook/document/pages/vue/vuex4.0.html" data-v-fc0d1b73><span class="desc" data-v-fc0d1b73>Next page</span><span class="title" data-v-fc0d1b73>vuex4.0</span></a></div></div></footer><!--[--><!--]--></div></div></div><!--[--><!--]--></div></div><!----><!--[--><!--]--></div></div>
    <script>__VP_HASH_MAP__ = JSON.parse("{\"pages_advancedprogramming_chapterone.md\":\"8fd81287\",\"pages_htmlcss_layout.md\":\"f07c901d\",\"index.md\":\"4ccfffb7\",\"pages_advancedprogramming_index.md\":\"3885217d\",\"code_fe-rec_readme.md\":\"71d0c648\",\"readme.md\":\"df521108\",\"code_virtual-list_readme.md\":\"17e862f9\",\"pages_guide.md\":\"706d8779\",\"pages_jsbase_typeconversion.md\":\"df6df8ff\",\"pages_htmlcss_bfc.md\":\"21d6a345\",\"pages_jsbase_cookielocal.md\":\"07b498fe\",\"pages_jsbase_datatype.md\":\"6076c1b6\",\"pages_jsbase_prototype.md\":\"6b57d6e9\",\"pages_htmlcss_htmlcss.md\":\"8b4e53c2\",\"pages_advancedprogramming_chaptertwo.md\":\"ad76f5b8\",\"pages_advancedprogramming_chapterthree.md\":\"8207f883\",\"pages_htmlcss_align.md\":\"8cc3e186\",\"pages_git.md\":\"5308b89e\",\"pages_jsbase_arrayapi.md\":\"751b1dff\",\"pages_htmlcss_boxmodel.md\":\"498a703b\",\"pages_htmlcss_position.md\":\"c5594a7c\",\"pages_jsbase_binary.md\":\"9b13b269\",\"pages_htmlcss_dice.md\":\"cc205c39\",\"pages_workreview_vuexpersistence.md\":\"1df9efec\",\"pages_workreview_reduxpersistence.md\":\"2f4f8ba5\",\"pages_webpack.md\":\"e8ec95fb\",\"pages_jsbase_scope.md\":\"268d233b\",\"pages_vue_vuex4.0.md\":\"98700d83\",\"pages_workreview_reactsolt.md\":\"2438b161\",\"pages_jsbase_this.md\":\"9d7c8fa7\",\"pages_workreview_virtuallist.md\":\"1db3bb5e\",\"code_big-files-upload_index.md\":\"49cc321f\",\"pages_jsbase_regular.md\":\"fea9b33d\",\"pages_jsbase_eventloop.md\":\"ddceb0f2\",\"pages_htmlcss_rem-em-vw.md\":\"f5e61910\",\"pages_optimize.md\":\"9b05a225\",\"pages_jsbase_promotion.md\":\"7da50ccc\",\"pages_jsbase_eightleggedessay.md\":\"560c41b2\",\"pages_jsbase_promise.md\":\"3d80d27b\",\"pages_vue_vuerouter4.0.md\":\"5ca24aaa\",\"pages_htmlcss_margin.md\":\"6fd000ce\",\"pages_flutter_index.md\":\"b69ef00b\",\"pages_workreview_interfacesignaturedesign.md\":\"98a64266\",\"pages_workreview_stripe.md\":\"68fbf713\",\"pages_http.md\":\"42149b78\",\"pages_nginx.md\":\"76adfb79\",\"pages_nodejs_nest.md\":\"340072bd\",\"pages_updatelog.md\":\"3a8f3b74\",\"pages_linux.md\":\"db194270\",\"pages_nodejs_index.md\":\"b91cc4fe\",\"pages_ssr.md\":\"29ae7526\",\"pages_vue_vue2.0.md\":\"ddaba816\",\"pages_resume.md\":\"e770c83b\",\"pages_react_react.md\":\"dd542d19\",\"pages_workreview_monitor.md\":\"bef20b19\",\"pages_react_redux.md\":\"a3c335fe\",\"pages_workreview_bigfileupload.md\":\"93f0370f\",\"pages_datastructure.md\":\"60632978\",\"pages_workreview_imagecroppingcompression.md\":\"3273dca0\",\"pages_jsbase_coding.md\":\"fd837602\",\"pages_xss-csrf.md\":\"afbef4b3\",\"pages_designpatterns.md\":\"7ba6c4c8\",\"pages_workreview_imagedragverification.md\":\"de2e29d5\",\"pages_workreview_audio.md\":\"e00ea8e1\",\"pages_workreview_axiospackaging.md\":\"e241a1bb\",\"pages_htmlcss_grid.md\":\"fee00858\",\"pages_vue_vue3.0.md\":\"21ba1254\",\"pages_jsbase_typescript.md\":\"48ee2090\"}")
__VP_SITE_DATA__ = JSON.parse("{\"lang\":\"en-US\",\"dir\":\"ltr\",\"title\":\"前端码农\",\"description\":\"前端码农手记\",\"base\":\"/fe-handbook/document/\",\"head\":[],\"appearance\":true,\"themeConfig\":{\"lastUpdatedText\":\"上次更新\",\"logo\":\"images/logo.svg\",\"nav\":[{\"text\":\"主页\",\"link\":\"/\"},{\"text\":\"指南\",\"link\":\"/pages/guide\"},{\"text\":\"更新日志\",\"link\":\"/pages/updateLog\"}],\"socialLinks\":[],\"sidebar\":[{\"collapsed\":false,\"items\":[{\"text\":\"开发指南\",\"link\":\"/pages/guide\"}]},{\"text\":\"JavaScript高级程序设计\",\"collapsed\":false,\"items\":[{\"text\":\"0.前言\",\"link\":\"/pages/advancedProgramming/index.md\"},{\"text\":\"1.什么是JavaScript\",\"link\":\"/pages/advancedProgramming/chapterOne.md\"},{\"text\":\"2.HTML中的JavaScript\",\"link\":\"/pages/advancedProgramming/chapterTwo.md\"},{\"text\":\"3.语言基础\",\"link\":\"/pages/advancedProgramming/chapterThree.md\"}]},{\"text\":\"vue技术栈\",\"collapsed\":false,\"items\":[{\"text\":\"vue2.0\",\"link\":\"/pages/vue/vue2.0.md\"},{\"text\":\"vue3.0\",\"link\":\"/pages/vue/vue3.0.md\"},{\"text\":\"vuex4.0\",\"link\":\"/pages/vue/vuex4.0.md\"}]},{\"text\":\"react技术栈\",\"collapsed\":false,\"items\":[{\"text\":\"react18\",\"link\":\"/pages/react/react.md\"},{\"text\":\"redux\",\"link\":\"/pages/react/redux.md\"}]},{\"text\":\"nodejs技术栈\",\"collapsed\":false,\"items\":[{\"text\":\"nodeJS\",\"link\":\"/pages/nodeJS/index.md\"},{\"text\":\"nest\",\"link\":\"/pages/nodeJS/nest.md\"}]},{\"text\":\"flutter\",\"collapsed\":false,\"items\":[{\"text\":\"flutter\",\"link\":\"/pages/flutter/index.md\"}]},{\"text\":\"数据结构算法&设计模式\",\"collapsed\":false,\"items\":[{\"text\":\"dataStructure\",\"link\":\"/pages/dataStructure.md\"},{\"text\":\"设计模式\",\"link\":\"/pages/designPatterns.md\"}]},{\"text\":\"js基础进阶\",\"collapsed\":false,\"items\":[{\"text\":\"数据类型\",\"link\":\"/pages/jsBase/dataType.md\"},{\"text\":\"数据类型转换\",\"link\":\"/pages/jsBase/typeConversion.md\"},{\"text\":\"原型与原型链\",\"link\":\"/pages/jsBase/prototype.md\"},{\"text\":\"闭包\",\"link\":\"/pages/jsBase/scope.md\"},{\"text\":\"this指针\",\"link\":\"/pages/jsBase/this.md\"},{\"text\":\"JS中的变量提升和函数提升\",\"link\":\"/pages/jsBase/promotion.md\"},{\"text\":\"异步&事件循环机制\",\"link\":\"/pages/jsBase/eventLoop.md\"},{\"text\":\"promise\",\"link\":\"/pages/jsBase/promise.md\"},{\"text\":\"cookie&local\",\"link\":\"/pages/jsBase/cookieLocal.md\"},{\"text\":\"arrayApi\",\"link\":\"/pages/jsBase/arrayApi.md\"},{\"text\":\"正则\",\"link\":\"/pages/jsBase/regular.md\"},{\"text\":\"coding\",\"link\":\"/pages/jsBase/coding.md\"},{\"text\":\"typescript\",\"link\":\"/pages/jsBase/typescript.md\"}]},{\"text\":\"前端综合\",\"collapsed\":false,\"items\":[{\"text\":\"前端八股文\",\"link\":\"/pages/jsBase/eightLeggedEssay.md\"},{\"text\":\"二进制\",\"link\":\"/pages/jsBase/binary.md\"},{\"text\":\"ssr\",\"link\":\"/pages/ssr.md\"},{\"text\":\"webpack\",\"link\":\"/pages/webpack.md\"},{\"text\":\"http\",\"link\":\"/pages/http.md\"},{\"text\":\"性能优化\",\"link\":\"/pages/optimize.md\"},{\"text\":\"xss-csrf\",\"link\":\"/pages/xss-csrf.md\"},{\"text\":\"linux\",\"link\":\"/pages/linux.md\"},{\"text\":\"nginx\",\"link\":\"/pages/nginx.md\"},{\"text\":\"git管理\",\"link\":\"/pages/git.md\"}]},{\"text\":\"工作复盘\",\"collapsed\":false,\"items\":[{\"text\":\"stripe支付体检优化\",\"link\":\"/pages/workReview/stripe.md\"},{\"text\":\"接口签名设计\",\"link\":\"/pages/workReview/interfaceSignatureDesign.md\"},{\"text\":\"redux数据持久化\",\"link\":\"/pages/workReview/reduxpersistence.md\"},{\"text\":\"vuex数据持久化\",\"link\":\"/pages/workReview/vuexpersistence.md\"},{\"text\":\"react插槽设计\",\"link\":\"/pages/workReview/reactSolt.md\"},{\"text\":\"大文件上传\",\"link\":\"/pages/workReview/bigfileUpload.md\"},{\"text\":\"音频录制\",\"link\":\"/pages/workReview/audio.md\"},{\"text\":\"虚拟列表\",\"link\":\"/pages/workReview/virtuaLlist.md\"},{\"text\":\"图片裁剪&压缩\",\"link\":\"/pages/workReview/imageCroppingCompression.md\"},{\"text\":\"axios封装\",\"link\":\"/pages/workReview/axiosPackaging.md\"},{\"text\":\"前端监控SDK\",\"link\":\"/pages/workReview/monitor.md\"},{\"text\":\"图片拖动验证\",\"link\":\"/pages/workReview/ImagedragVerification.md\"}]},{\"text\":\"html/css\",\"collapsed\":false,\"items\":[{\"text\":\"盒模型\",\"link\":\"/pages/htmlCss/boxModel.md\"},{\"text\":\"margin重叠\",\"link\":\"/pages/htmlCss/margin.md\"},{\"text\":\"bfc\",\"link\":\"/pages/htmlCss/bfc.md\"},{\"text\":\"圣杯布局&双飞翼布局\",\"link\":\"/pages/htmlCss/layout.md\"},{\"text\":\"flex画骰子\",\"link\":\"/pages/htmlCss/dice.md\"},{\"text\":\"position定位\",\"link\":\"/pages/htmlCss/position.md\"},{\"text\":\"对齐\",\"link\":\"/pages/htmlCss/align.md\"},{\"text\":\"rem-em-vw\",\"link\":\"/pages/htmlCss/rem-em-vw.md\"},{\"text\":\"grid布局\",\"link\":\"/pages/htmlCss/grid.md\"},{\"text\":\"htmlCss总结\",\"link\":\"/pages/htmlCss/htmlCss.md\"}]}]},\"locales\":{},\"scrollOffset\":90,\"cleanUrls\":false}")</script>
    
  </body>
</html>